From 1091c17aaf7b30cf7bfabc0745d84ed689819b11 Mon Sep 17 00:00:00 2001 From: Savin Mikhail Date: Fri, 3 Oct 2025 09:50:59 +0300 Subject: [PATCH] style(rector): add named arguments rule --- composer.json | 3 +- rector.php | 5 + .../Bootloader/ConfigurationBootloader.php | 3 +- .../Bootloader/ConsoleBootloader.php | 6 +- src/Application/Bootloader/CoreBootloader.php | 10 +- .../Bootloader/LoggerBootloader.php | 8 +- src/Application/Directories.php | 10 +- .../Dispatcher/ConsoleDispatcher.php | 8 +- src/Application/ExceptionHandler.php | 22 ++-- src/Application/FSPath.php | 84 ++++++------- src/Application/Kernel.php | 6 +- src/Application/Logger/ConsoleLogger.php | 14 +-- src/Application/Logger/FileLogger.php | 2 +- src/Application/Logger/LogLevel.php | 4 +- src/Application/Logger/SimpleFormatter.php | 14 +-- src/Config/ConfigLoaderBootloader.php | 8 +- src/Config/ConfigType.php | 6 +- src/Config/ConfigurationProvider.php | 6 +- src/Config/Exclude/AbstractExclusion.php | 4 +- src/Config/Exclude/ExcludeBootloader.php | 2 +- src/Config/Exclude/ExcludeParserPlugin.php | 24 ++-- src/Config/Exclude/ExcludeRegistry.php | 6 +- src/Config/Exclude/PathExclusion.php | 6 +- src/Config/Exclude/PatternExclusion.php | 4 +- src/Config/Import/CircularImportDetector.php | 12 +- src/Config/Import/ImportParserPlugin.php | 10 +- src/Config/Import/ImportRegistry.php | 2 +- src/Config/Import/ImportResolver.php | 62 +++++----- .../Import/Merger/AbstractConfigMerger.php | 14 +-- src/Config/Import/PathMatcher.php | 22 ++-- .../DocumentOutputPathPrefixer.php | 4 +- .../Import/PathPrefixer/PathPrefixer.php | 18 +-- .../PathPrefixer/SourcePathPrefixer.php | 22 ++-- .../Import/Source/AbstractImportSource.php | 22 ++-- .../Source/Config/AbstractSourceConfig.php | 2 +- .../Source/Config/SourceConfigFactory.php | 6 +- .../Import/Source/ImportSourceProvider.php | 8 +- src/Config/Import/Source/ImportedConfig.php | 6 +- .../Import/Source/Local/LocalImportSource.php | 42 +++---- .../Import/Source/Local/LocalSourceConfig.php | 14 +-- .../Local/MarkdownToResourceTransformer.php | 52 ++++---- .../Source/Registry/ImportSourceRegistry.php | 4 +- .../Import/Source/Url/UrlImportSource.php | 36 +++--- .../Import/Source/Url/UrlSourceConfig.php | 10 +- src/Config/Import/WildcardPathFinder.php | 46 +++---- src/Config/ImportBootloader.php | 6 +- src/Config/Loader/CompositeConfigLoader.php | 10 +- src/Config/Loader/ConfigLoader.php | 2 +- src/Config/Loader/ConfigLoaderFactory.php | 18 +-- src/Config/Parser/CompositeConfigParser.php | 4 +- src/Config/Parser/ConfigParser.php | 4 +- src/Config/Parser/VariablesParserPlugin.php | 10 +- src/Config/Reader/AbstractReader.php | 10 +- src/Config/Reader/ConfigReaderRegistry.php | 6 +- src/Config/Reader/JsonReader.php | 4 +- src/Config/Reader/MarkdownDirectoryReader.php | 22 ++-- src/Config/Reader/MarkdownMetadataReader.php | 56 ++++----- src/Config/Reader/PhpReader.php | 12 +- src/Config/Reader/StringJsonReader.php | 6 +- src/Config/Reader/YamlReader.php | 6 +- src/Config/Registry/ConfigRegistry.php | 10 +- .../Registry/ConfigRegistryAccessor.php | 12 +- src/Console/BaseCommand.php | 6 +- src/Console/GenerateCommand.php | 20 +-- .../Renderer/GenerateCommandRenderer.php | 46 +++---- src/Console/Renderer/Style.php | 8 +- src/Console/SelfUpdateCommand.php | 35 +++--- src/Console/VersionCommand.php | 14 +-- src/Directories.php | 28 ++--- src/Document/Compiler/DocumentCompiler.php | 46 +++---- .../Compiler/Error/ErrorCollection.php | 8 +- src/Document/Compiler/Error/SourceError.php | 2 +- src/Document/Document.php | 12 +- src/Document/DocumentConfigMerger.php | 2 +- src/Document/DocumentRegistry.php | 8 +- src/Document/DocumentsParserPlugin.php | 22 ++-- src/Lib/BinaryUpdater/BinaryUpdater.php | 6 +- .../Strategy/UnixUpdateStrategy.php | 30 ++--- .../Strategy/WindowsUpdateStrategy.php | 36 +++--- src/Lib/BinaryUpdater/UpdaterFactory.php | 4 +- .../FileSystemComposerClient.php | 24 ++-- src/Lib/Content/Block/FileStatsBlock.php | 6 +- src/Lib/Content/Block/TextBlock.php | 2 +- src/Lib/Content/ContentBuilder.php | 24 ++-- src/Lib/Content/ContentBuilderFactory.php | 2 +- src/Lib/Content/Renderer/AbstractRenderer.php | 2 +- src/Lib/Content/Renderer/MarkdownRenderer.php | 8 +- src/Lib/Context7Client/Context7Client.php | 42 +++---- src/Lib/Context7Client/Model/Library.php | 2 +- .../Model/LibrarySearchResult.php | 10 +- src/Lib/Finder/FinderResult.php | 2 +- src/Lib/Git/Command.php | 20 +-- src/Lib/Git/CommandsExecutor.php | 56 ++++----- src/Lib/Git/Exception/GitClientException.php | 2 +- src/Lib/GithubClient/Architecture.php | 6 +- src/Lib/GithubClient/BinaryNameBuilder.php | 8 +- src/Lib/GithubClient/GithubClient.php | 24 ++-- .../GithubClient/Model/GithubRepository.php | 4 +- src/Lib/GithubClient/Model/Release.php | 6 +- src/Lib/GithubClient/Platform.php | 2 +- src/Lib/GithubClient/ReleaseManager.php | 34 +++--- src/Lib/GitlabClient/GitlabClient.php | 38 +++--- .../GitlabClient/Model/GitlabRepository.php | 4 +- src/Lib/Html/HtmlCleaner.php | 4 +- src/Lib/Html/SelectorContentExtractor.php | 20 +-- src/Lib/HttpClient/HttpClientBootloader.php | 2 +- src/Lib/HttpClient/HttpResponse.php | 26 ++-- src/Lib/HttpClient/Psr18Client.php | 12 +- src/Lib/PathFilter/AbstractFilter.php | 12 +- src/Lib/PathFilter/ContentsFilter.php | 14 +-- src/Lib/PathFilter/ExcludePathFilter.php | 18 +-- src/Lib/PathFilter/FileHelper.php | 12 +- src/Lib/PathFilter/FilePatternFilter.php | 4 +- src/Lib/PathFilter/PathFilter.php | 4 +- src/Lib/TokenCounter/CharTokenCounter.php | 14 +-- src/Lib/TreeBuilder/DirectorySorter.php | 40 +++--- src/Lib/TreeBuilder/FileTreeBuilder.php | 36 +++--- .../TreeRenderer/AsciiTreeRenderer.php | 54 ++++----- src/Lib/TreeBuilder/TreeViewConfig.php | 8 +- src/Lib/Variable/CompositeProcessor.php | 2 +- .../Provider/CompositeVariableProvider.php | 2 +- .../Provider/ConfigVariableProvider.php | 6 +- .../Provider/DotEnvVariableProvider.php | 2 +- .../Provider/PredefinedVariableProvider.php | 8 +- src/Lib/Variable/VariableBootloader.php | 4 +- .../Variable/VariableReplacementProcessor.php | 12 +- src/Lib/Variable/VariableResolver.php | 6 +- .../Prompts/FilesystemOperationsAction.php | 2 +- .../Action/Prompts/ListPromptsAction.php | 2 +- .../Action/Resources/GenerateConfigAction.php | 28 ++--- .../GetDocumentContentResourceAction.php | 6 +- .../Resources/JsonSchemaResourceAction.php | 4 +- .../Action/Resources/ListResourcesAction.php | 4 +- .../Action/Tools/Context/ContextAction.php | 8 +- .../Action/Tools/Context/ContextGetAction.php | 12 +- .../Tools/Context/ContextRequestAction.php | 12 +- .../Tools/Docs/FetchLibraryDocsAction.php | 12 +- .../Action/Tools/Docs/LibrarySearchAction.php | 10 +- .../Action/Tools/ExecuteCustomToolAction.php | 8 +- .../Tools/Filesystem/DirectoryListAction.php | 46 +++---- .../Tools/Filesystem/FileApplyPatchAction.php | 14 +-- .../Tools/Filesystem/FileMoveAction.php | 20 +-- .../Tools/Filesystem/FileReadAction.php | 14 +-- .../Tools/Filesystem/FileWriteAction.php | 16 +-- .../Action/Tools/Git/GitAddAction.php | 26 ++-- .../Action/Tools/Git/GitCommitAction.php | 26 ++-- .../Action/Tools/Git/GitStatusAction.php | 18 +-- .../Action/Tools/ListToolsAction.php | 6 +- .../Tools/Prompts/GetPromptToolAction.php | 22 ++-- .../Tools/Prompts/ListPromptsToolAction.php | 6 +- src/McpServer/ActionsBootloader.php | 6 +- src/McpServer/Console/MCPServerCommand.php | 8 +- src/McpServer/Console/McpConfigCommand.php | 20 +-- src/McpServer/HttpTransportBootloader.php | 4 +- src/McpServer/Middleware/AuthMiddleware.php | 2 +- .../Actions/Dto/ProjectSwitchResponse.php | 4 +- .../Actions/ProjectSwitchToolAction.php | 24 ++-- .../Actions/ProjectsListToolAction.php | 8 +- .../Projects/Console/ProjectAddCommand.php | 8 +- .../Projects/Console/ProjectCommand.php | 24 ++-- .../Projects/Console/ProjectListCommand.php | 12 +- .../Prompt/Console/ListPromptsCommand.php | 34 +++--- .../Prompt/Console/ShowPromptCommand.php | 98 +++++++-------- .../Tool/Console/ToolListCommand.php | 30 ++--- src/McpServer/Tool/Console/ToolRunCommand.php | 96 +++++++-------- .../Alias/ModifierAliasesParserPlugin.php | 8 +- src/Modifier/Alias/ModifierResolver.php | 14 +-- src/Modifier/Modifier.php | 6 +- src/Modifier/ModifierBootloader.php | 2 +- src/Modifier/ModifiersApplier.php | 10 +- .../PhpContentFilter/PhpContentFilter.php | 88 +++++++------- src/Modifier/PhpDocs/AstDocTransformer.php | 102 ++++++++-------- src/Modifier/PhpSignature/PhpSignature.php | 38 +++--- .../Sanitizer/Rule/CommentInsertionRule.php | 30 ++--- .../Sanitizer/Rule/KeywordRemovalRule.php | 10 +- .../Sanitizer/Rule/RegexReplacementRule.php | 2 +- src/Modifier/Sanitizer/Rule/RuleFactory.php | 24 ++-- src/Modifier/Sanitizer/SanitizerModifier.php | 6 +- src/Source/BaseSource.php | 8 +- src/Source/Composer/ComposerSource.php | 4 +- .../Composer/ComposerSourceBootloader.php | 2 +- src/Source/Composer/ComposerSourceFactory.php | 6 +- src/Source/Composer/ComposerSourceFetcher.php | 54 ++++----- .../Package/ComposerPackageCollection.php | 20 +-- .../Composer/Package/ComposerPackageInfo.php | 32 ++--- .../Provider/AbstractComposerProvider.php | 8 +- .../Provider/CompositeComposerProvider.php | 8 +- .../Provider/LocalComposerProvider.php | 34 +++--- src/Source/Docs/DocsSource.php | 4 +- src/Source/Docs/DocsSourceBootloader.php | 2 +- src/Source/Docs/DocsSourceFactory.php | 10 +- src/Source/Docs/DocsSourceFetcher.php | 36 +++--- .../Fetcher/SourceFetcherBootloader.php | 4 +- src/Source/Fetcher/SourceFetcherProvider.php | 4 +- src/Source/File/FileSource.php | 6 +- src/Source/File/FileSourceBootloader.php | 2 +- src/Source/File/FileSourceFactory.php | 32 ++--- src/Source/File/FileSourceFetcher.php | 30 ++--- src/Source/File/SymfonyFinder.php | 30 ++--- .../GitDiff/Fetcher/CommitRangeParser.php | 24 ++-- .../GitDiff/Fetcher/GitSourceFactory.php | 2 +- .../Fetcher/Source/AbstractGitSource.php | 12 +- .../Fetcher/Source/CommitGitSource.php | 6 +- .../Fetcher/Source/FileAtCommitGitSource.php | 16 +-- .../GitDiff/Fetcher/Source/StashGitSource.php | 36 +++--- .../Fetcher/Source/TimeRangeGitSource.php | 16 +-- src/Source/GitDiff/GitDiffFinder.php | 50 ++++---- src/Source/GitDiff/GitDiffSource.php | 4 +- .../GitDiff/GitDiffSourceBootloader.php | 2 +- src/Source/GitDiff/GitDiffSourceFactory.php | 28 ++--- src/Source/GitDiff/GitDiffSourceFetcher.php | 46 +++---- .../RenderStrategy/Config/RenderConfig.php | 6 +- .../Enum/RenderStrategyEnum.php | 6 +- .../LLMFriendlyRenderStrategy.php | 40 +++--- .../RenderStrategy/RawRenderStrategy.php | 8 +- .../RenderStrategy/RenderStrategyFactory.php | 4 +- src/Source/Github/GithubFileInfo.php | 2 +- src/Source/Github/GithubFinder.php | 52 ++++---- src/Source/Github/GithubSource.php | 4 +- src/Source/Github/GithubSourceBootloader.php | 2 +- src/Source/Github/GithubSourceFactory.php | 18 +-- src/Source/Github/GithubSourceFetcher.php | 22 ++-- .../Config/GitlabServerParserPlugin.php | 12 +- src/Source/Gitlab/Config/ServerConfig.php | 12 +- src/Source/Gitlab/Config/ServerRegistry.php | 4 +- src/Source/Gitlab/GitlabFileInfo.php | 2 +- src/Source/Gitlab/GitlabFinder.php | 52 ++++---- src/Source/Gitlab/GitlabSource.php | 4 +- src/Source/Gitlab/GitlabSourceBootloader.php | 4 +- src/Source/Gitlab/GitlabSourceFactory.php | 24 ++-- src/Source/Gitlab/GitlabSourceFetcher.php | 24 ++-- src/Source/Registry/AbstractSourceFactory.php | 2 +- src/Source/Registry/SourceRegistry.php | 2 +- src/Source/Text/TextSource.php | 4 +- src/Source/Text/TextSourceBootloader.php | 2 +- src/Source/Text/TextSourceFactory.php | 4 +- src/Source/Text/TextSourceFetcher.php | 16 +-- src/Source/Tree/TreeSource.php | 6 +- src/Source/Tree/TreeSourceBootloader.php | 2 +- src/Source/Tree/TreeSourceFactory.php | 36 +++--- src/Source/Tree/TreeSourceFetcher.php | 12 +- src/Source/Url/UrlSource.php | 6 +- src/Source/Url/UrlSourceBootloader.php | 2 +- src/Source/Url/UrlSourceFactory.php | 6 +- src/Source/Url/UrlSourceFetcher.php | 46 +++---- tests/src/AppTestCase.php | 10 +- .../Compiler/AbstractCompilerTestCase.php | 52 ++++---- .../GenerateCommand/CompilingResult.php | 4 +- .../GenerateCommand/ContextBuilder.php | 14 +-- .../Console/GenerateCommand/ExcludeTest.php | 2 +- .../GenerateCommand/FileSourceTest.php | 2 +- .../GenerateCommand/GenerateCommandTest.php | 4 +- .../GenerateCommand/GithubSourceTest.php | 4 +- .../GenerateCommand/GitlabSourceTest.php | 4 +- .../GenerateCommand/LocalImportTest.php | 32 ++--- .../GenerateCommand/MockGithubClient.php | 4 +- .../GenerateCommand/MockGitlabClient.php | 2 +- .../GenerateCommand/MockHttpClient.php | 2 +- .../GenerateCommand/PromptAssertions.php | 6 +- .../GenerateCommand/PromptValidationTest.php | 46 +++---- .../Console/GenerateCommand/PromptsTest.php | 114 +++++++++--------- .../GenerateCommand/ToolAssertions.php | 28 ++--- .../Console/GenerateCommand/ToolsTest.php | 68 +++++------ .../Console/GenerateCommand/UrlImportTest.php | 62 +++++----- .../Console/GenerateCommand/UrlSourceTest.php | 36 +++--- tests/src/Feature/FeatureTestCases.php | 10 +- .../FileStorage/DirectoryScannerTest.php | 94 +++++++-------- .../FileStorage/FrontmatterParserTest.php | 22 ++-- .../File/AbstractFileSourceTestCase.php | 12 +- .../Source/File/FileSourceFilterTest.php | 2 +- .../File/FileSourceSerializationTest.php | 12 +- .../Feature/Source/File/FileSourceTest.php | 2 +- .../Source/File/FileSourceTreeViewTest.php | 2 +- tests/src/TestCase.php | 20 +-- .../src/Unit/Application/FSPathLinuxTest.php | 68 +++++------ .../Unit/Application/FSPathMixedSlashTest.php | 94 +++++++-------- .../Unit/Application/FSPathWindowsTest.php | 60 ++++----- tests/src/Unit/DirectoriesTest.php | 30 ++--- .../Compiler/DocumentCompilerTest.php | 40 +++--- tests/src/Unit/Document/DocumentTest.php | 10 +- .../Unit/Fetcher/FileSourceFetcherTest.php | 4 +- .../src/Unit/Fetcher/FileTreeBuilderTest.php | 8 +- .../Unit/Fetcher/TextSourceFetcherTest.php | 8 +- tests/src/Unit/Lib/Html/HtmlCleanerTest.php | 6 +- .../Sanitizer/CommentInsertionRuleTest.php | 16 +-- .../Lib/Sanitizer/ContextSanitizerTest.php | 30 ++--- .../Lib/Sanitizer/KeywordRemovalRuleTest.php | 20 +-- .../Sanitizer/RegexReplacementRuleTest.php | 20 +-- .../Unit/Lib/Sanitizer/RuleFactoryTest.php | 40 +++--- .../Lib/TokenCounter/CharTokenCounterTest.php | 32 ++--- .../Lib/TreeBuilder/DirectorySorterTest.php | 42 +++---- .../Lib/TreeBuilder/FileTreeBuilderTest.php | 74 ++++++------ .../CompositeVariableProviderTest.php | 16 +-- .../Provider/DotEnvVariableProviderTest.php | 22 ++-- .../PredefinedVariableProviderTest.php | 34 +++--- .../VariableReplacementProcessorTest.php | 36 +++--- .../Lib/Variable/VariableResolverTest.php | 42 +++---- .../Variable/VariableSystemEdgeCasesTest.php | 38 +++--- .../VariableSystemIntegrationTest.php | 38 +++--- .../Unit/Source/BaseSourceConstructorTest.php | 2 +- .../Unit/Source/FileSourceConstructorTest.php | 2 +- .../Unit/Source/FileSourceFromArrayTest.php | 26 ++-- .../Fetcher/Source/CommitGitSourceTest.php | 42 +++---- .../Source/FileAtCommitGitSourceTest.php | 30 ++--- .../Fetcher/Source/GitSourceTestCase.php | 10 +- .../Fetcher/Source/StagedGitSourceTest.php | 30 ++--- .../Fetcher/Source/StashGitSourceTest.php | 36 +++--- .../Fetcher/Source/TimeRangeGitSourceTest.php | 54 ++++----- .../Fetcher/Source/UnstagedGitSourceTest.php | 30 ++--- .../LLMFriendlyRenderStrategyTest.php | 8 +- .../RenderStrategy/RawRenderStrategyTest.php | 6 +- .../RenderStrategyFactoryTest.php | 4 +- .../Unit/Source/TextSourceFromArrayTest.php | 2 +- .../Unit/Source/Url/UrlSourceFetcherTest.php | 28 ++--- tests/src/Unit/Source/Url/UrlSourceTest.php | 12 +- 315 files changed, 2876 insertions(+), 2872 deletions(-) diff --git a/composer.json b/composer.json index 6143cb94..0627db7c 100644 --- a/composer.json +++ b/composer.json @@ -43,7 +43,8 @@ "spiral/code-style": "^2.2.2", "spiral/testing": "^2.9", "rector/rector": "^2.0", - "vimeo/psalm": "^6.0" + "vimeo/psalm": "^6.0", + "savinmikhail/add_named_arguments_rector": "^0.1.19" }, "autoload": { "psr-4": { diff --git a/rector.php b/rector.php index 9b5f8f95..7f77b25b 100644 --- a/rector.php +++ b/rector.php @@ -5,6 +5,7 @@ use Rector\Config\RectorConfig; use Rector\Set\ValueObject\LevelSetList; use Rector\Set\ValueObject\SetList; +use SavinMikhail\AddNamedArgumentsRector\AddNamedArgumentsRector; return static function (RectorConfig $rectorConfig): void { $rectorConfig->paths([ @@ -22,4 +23,8 @@ $rectorConfig->skip([ __DIR__ . '/vendor', ]); + + $rectorConfig->rules([ + AddNamedArgumentsRector::class, + ]); }; diff --git a/src/Application/Bootloader/ConfigurationBootloader.php b/src/Application/Bootloader/ConfigurationBootloader.php index 1f947a4c..af54b30e 100644 --- a/src/Application/Bootloader/ConfigurationBootloader.php +++ b/src/Application/Bootloader/ConfigurationBootloader.php @@ -58,8 +58,7 @@ public function addLoader(string $ext, FileLoaderInterface $loader): void private function createConfigManager(): ConfigManager { return new ConfigManager( - new DirectoryLoader($this->directories->get('config'), $this->loaders), - true, + loader: new DirectoryLoader(directory: $this->directories->get('config'), loaders: $this->loaders), ); } diff --git a/src/Application/Bootloader/ConsoleBootloader.php b/src/Application/Bootloader/ConsoleBootloader.php index d59dd513..f06050af 100644 --- a/src/Application/Bootloader/ConsoleBootloader.php +++ b/src/Application/Bootloader/ConsoleBootloader.php @@ -27,7 +27,7 @@ public function __construct( public function init(AbstractKernel $kernel, BinderInterface $binder, Application $app): void { $kernel->bootstrapped(static function (AbstractKernel $kernel): void { - $kernel->addDispatcher(ConsoleDispatcher::class); + $kernel->addDispatcher(dispatcher: ConsoleDispatcher::class); }); // Registering necessary scope bindings @@ -53,7 +53,7 @@ public function addInterceptor(string ...$interceptors): void foreach ($interceptors as $interceptor) { $this->config->modify( ConsoleConfig::CONFIG, - new Append('interceptors', null, $interceptor), + new Append(position: 'interceptors', key: null, value: $interceptor), ); } } @@ -66,7 +66,7 @@ public function addCommand(string ...$commands): void foreach ($commands as $command) { $this->config->modify( ConsoleConfig::CONFIG, - new Append('commands', null, $command), + new Append(position: 'commands', key: null, value: $command), ); } } diff --git a/src/Application/Bootloader/CoreBootloader.php b/src/Application/Bootloader/CoreBootloader.php index f821b680..b4e027ff 100644 --- a/src/Application/Bootloader/CoreBootloader.php +++ b/src/Application/Bootloader/CoreBootloader.php @@ -47,7 +47,7 @@ interface: \Butschster\ContextGenerator\DirectoriesInterface::class, public function init(DirectoriesInterface $dirs, EnvironmentInterface $env): void { - $this->loadEnvVariables($dirs, $env); + $this->loadEnvVariables(dirs: $dirs, env: $env); } public function boot(ConsoleBootloader $console): void @@ -70,14 +70,14 @@ public function loadEnvVariables(DirectoriesInterface $dirs, EnvironmentInterfac $dotenvPath = $env->get('DOTENV_PATH', $dirs->get('root') . '.env'); - if (!\file_exists($dotenvPath)) { + if (!\file_exists(filename: $dotenvPath)) { return; } - $path = \dirname((string) $dotenvPath); - $file = \basename((string) $dotenvPath); + $path = \dirname(path: (string) $dotenvPath); + $file = \basename(path: (string) $dotenvPath); - foreach (Dotenv::createImmutable($path, $file)->load() as $key => $value) { + foreach (Dotenv::createImmutable(paths: $path, names: $file)->load() as $key => $value) { $env->set($key, $value); } } diff --git a/src/Application/Bootloader/LoggerBootloader.php b/src/Application/Bootloader/LoggerBootloader.php index abe953a5..4c7a259a 100644 --- a/src/Application/Bootloader/LoggerBootloader.php +++ b/src/Application/Bootloader/LoggerBootloader.php @@ -58,14 +58,14 @@ public function boot(BinderInterface $binder, ExceptionHandler $handler, FileSna // Register injectable class $binder->bindInjector(LoggerInterface::class, self::class); $handler->addReporter( - new readonly class($snapshot) implements ExceptionReporterInterface { + reporter: new readonly class($snapshot) implements ExceptionReporterInterface { public function __construct( private FileSnapshot $fileSnapshot, ) {} public function report(\Throwable $exception): void { - $this->fileSnapshot->create($exception); + $this->fileSnapshot->create(e: $exception); } }, ); @@ -77,7 +77,7 @@ public function createInjection(\ReflectionClass $class, mixed $context = null): $prefix = null; if ($context instanceof \ReflectionParameter) { - $prefix = $this->findAttribute($context)?->prefix ?? $context->getDeclaringClass()->getShortName(); + $prefix = $this->findAttribute(parameter: $context)?->prefix ?? $context->getDeclaringClass()->getShortName(); } if (!$prefix) { @@ -89,7 +89,7 @@ public function createInjection(\ReflectionClass $class, mixed $context = null): private function findAttribute(\ReflectionParameter $parameter): ?LoggerPrefix { - foreach ($parameter->getAttributes(LoggerPrefix::class) as $attribute) { + foreach ($parameter->getAttributes(name: LoggerPrefix::class) as $attribute) { return $attribute->newInstance(); } diff --git a/src/Application/Directories.php b/src/Application/Directories.php index 0e7da84d..a0d69153 100644 --- a/src/Application/Directories.php +++ b/src/Application/Directories.php @@ -16,26 +16,26 @@ public function __construct( private array $directories = [], ) { foreach ($directories as $name => $directory) { - $this->set($name, $directory); + $this->set(name: $name, path: $directory); } } public function has(string $name): bool { - return \array_key_exists($name, $this->directories); + return \array_key_exists(key: $name, array: $this->directories); } public function set(string $name, string $path): DirectoriesInterface { - $this->directories[$name] = \rtrim($path, '/') . '/'; + $this->directories[$name] = \rtrim(string: $path, characters: '/') . '/'; return $this; } public function get(string $name): string { - if (!$this->has($name)) { - throw new DirectoryException("Undefined directory '{$name}'"); + if (!$this->has(name: $name)) { + throw new DirectoryException(message: "Undefined directory '{$name}'"); } return $this->directories[$name]; diff --git a/src/Application/Dispatcher/ConsoleDispatcher.php b/src/Application/Dispatcher/ConsoleDispatcher.php index b1866233..a5cd94d9 100644 --- a/src/Application/Dispatcher/ConsoleDispatcher.php +++ b/src/Application/Dispatcher/ConsoleDispatcher.php @@ -35,14 +35,14 @@ public function serve(?InputInterface $input = null, ?OutputInterface $output = { $input ??= new ArgvInput(); // On demand to save some memory. - $output ??= new SymfonyStyle($input, new ConsoleOutput()); + $output ??= new SymfonyStyle(input: $input, output: new ConsoleOutput()); return $this->container->runScope( bindings: new Scope( name: 'console', ), scope: function (Container $container) use ($input, $output) { - $console = $container->get(Console::class); + $console = $container->get(id: Console::class); try { return $console->run( @@ -51,7 +51,7 @@ public function serve(?InputInterface $input = null, ?OutputInterface $output = $output, )->getCode(); } catch (\Throwable $e) { - $this->handleException($e, $output); + $this->handleException(exception: $e, output: $output); return 255; } finally { @@ -67,7 +67,7 @@ protected function handleException(\Throwable $exception, OutputInterface $outpu $output->write( $this->errorHandler->render( $exception, - verbosity: $this->mapVerbosity($output), + verbosity: $this->mapVerbosity(output: $output), format: 'cli', ), ); diff --git a/src/Application/ExceptionHandler.php b/src/Application/ExceptionHandler.php index c5d49644..49e2427b 100644 --- a/src/Application/ExceptionHandler.php +++ b/src/Application/ExceptionHandler.php @@ -24,14 +24,14 @@ final class ExceptionHandler implements ExceptionHandlerInterface, LoggerAwareIn public function __construct( #[Proxy] LoggerInterface $logger, ) { - $this->setLogger($logger); + $this->setLogger(logger: $logger); $this->handler = new \Spiral\Exceptions\ExceptionHandler(); $this->bootBasicHandlers(); } public function getRenderer(?string $format = null): ?ExceptionRendererInterface { - return $this->handler->getRenderer($format); + return $this->handler->getRenderer(format: $format); } public function setLogger(LoggerInterface $logger): void {} @@ -46,22 +46,22 @@ public function render( ?Verbosity $verbosity = Verbosity::BASIC, ?string $format = null, ): string { - return $this->handler->render($exception, $verbosity, $format); + return $this->handler->render(exception: $exception, verbosity: $verbosity, format: $format); } public function canRender(string $format): bool { - return $this->handler->canRender($format); + return $this->handler->canRender(format: $format); } public function report(\Throwable $exception): void { - $this->handler->report($exception); + $this->handler->report(exception: $exception); } public function handleGlobalException(\Throwable $e): void { - $this->handler->handleGlobalException($e); + $this->handler->handleGlobalException(e: $e); } /** @@ -69,7 +69,7 @@ public function handleGlobalException(\Throwable $e): void */ public function addRenderer(ExceptionRendererInterface $renderer): void { - $this->handler->addRenderer($renderer); + $this->handler->addRenderer(renderer: $renderer); } /** @@ -77,7 +77,7 @@ public function addRenderer(ExceptionRendererInterface $renderer): void */ public function dontReport(string $exception): void { - $this->handler->dontReport($exception); + $this->handler->dontReport(exception: $exception); } /** @@ -85,7 +85,7 @@ public function dontReport(string $exception): void */ public function addReporter(ExceptionReporterInterface|\Closure $reporter): void { - $this->handler->addReporter($reporter); + $this->handler->addReporter(reporter: $reporter); } /** @@ -93,11 +93,11 @@ public function addReporter(ExceptionReporterInterface|\Closure $reporter): void */ public function setOutput(mixed $output): void { - $this->handler->setOutput($output); + $this->handler->setOutput(output: $output); } protected function bootBasicHandlers(): void { - $this->addRenderer(new ConsoleRenderer()); + $this->addRenderer(renderer: new ConsoleRenderer()); } } diff --git a/src/Application/FSPath.php b/src/Application/FSPath.php index 09eabb37..89822108 100644 --- a/src/Application/FSPath.php +++ b/src/Application/FSPath.php @@ -75,11 +75,11 @@ public function join(string ...$paths): self continue; } - if ($result !== '' && !\str_ends_with($result, self::getDirectorySeparator())) { + if ($result !== '' && !\str_ends_with(haystack: $result, needle: self::getDirectorySeparator())) { $result .= self::getDirectorySeparator(); } - $result .= \ltrim($path, self::getDirectorySeparator()); + $result .= \ltrim(string: $path, characters: self::getDirectorySeparator()); } // We return the raw string, not a normalized path, since it's already normalized @@ -109,11 +109,11 @@ public function withExt(string $suffix): self $stem = $this->stem(); - if (!\str_starts_with($suffix, '.') && !empty($suffix)) { + if (!\str_starts_with(haystack: $suffix, needle: '.') && !empty($suffix)) { $suffix = '.' . $suffix; } - return $this->withName($stem . $suffix); + return $this->withName(name: $stem . $suffix); } /** @@ -131,7 +131,7 @@ public function withStem(string $stem): self $suffix = '.' . $suffix; } - return $this->withName($stem . $suffix); + return $this->withName(name: $stem . $suffix); } /** @@ -147,12 +147,12 @@ public function name(): string } // If the path is a single part, return the current directory - if (\count($parts) === 1) { + if (\count(value: $parts) === 1) { return $parts[0]; } // get the last part of the path - return \array_pop($parts); + return \array_pop(array: $parts); } /** @@ -161,13 +161,13 @@ public function name(): string public function stem(): string { $name = $this->name(); - $pos = \strrpos($name, '.'); + $pos = \strrpos(haystack: $name, needle: '.'); if ($pos === false || $pos === 0) { return $name; } - return \substr($name, 0, $pos); + return \substr(string: $name, offset: 0, length: $pos); } /** @@ -177,7 +177,7 @@ public function extension(): string { $name = $this->name(); - return \pathinfo($name, PATHINFO_EXTENSION); + return \pathinfo(path: $name, flags: PATHINFO_EXTENSION); } /** @@ -197,16 +197,16 @@ public function parent(): self } // If the path is a single part, return the current directory - if (\count($parts) === 1) { + if (\count(value: $parts) === 1) { return self::create('.'); } // Remove the last part to get the parent directory - $parts = \array_slice($parts, 0, -1); - $isAbsPath = \str_starts_with($this->path, self::getDirectorySeparator()); + $parts = \array_slice(array: $parts, offset: 0, length: -1); + $isAbsPath = \str_starts_with(haystack: $this->path, needle: self::getDirectorySeparator()); // If the path is absolute, ensure the first part is preserved - $path = \implode(self::getDirectorySeparator(), $parts); + $path = \implode(separator: self::getDirectorySeparator(), array: $parts); if ($isAbsPath) { $path = self::getDirectorySeparator() . $path; } @@ -220,8 +220,8 @@ public function parent(): self */ public function parts(): array { - $normalizedPath = \str_replace(['\\', '/'], self::getDirectorySeparator(), $this->path); - return \array_values(\array_filter(\explode(self::getDirectorySeparator(), $normalizedPath), \strlen(...))); + $normalizedPath = \str_replace(search: ['\\', '/'], replace: self::getDirectorySeparator(), subject: $this->path); + return \array_values(array: \array_filter(array: \explode(separator: self::getDirectorySeparator(), string: $normalizedPath), callback: \strlen(...))); } /** @@ -245,7 +245,7 @@ public function isRelative(): bool */ public function exists(): bool { - return \file_exists($this->path); + return \file_exists(filename: $this->path); } /** @@ -253,7 +253,7 @@ public function exists(): bool */ public function isDir(): bool { - return \is_dir($this->path); + return \is_dir(filename: $this->path); } /** @@ -261,7 +261,7 @@ public function isDir(): bool */ public function isFile(): bool { - return \is_file($this->path); + return \is_file(filename: $this->path); } /** @@ -271,8 +271,8 @@ public function relativeTo(self $other): self { // If paths are on different drives (Windows), return the absolute path if (self::getDirectorySeparator() === '\\') { - $thisRoot = $this->_getWindowsDrive($this->path); - $otherRoot = $this->_getWindowsDrive($other->path); + $thisRoot = $this->_getWindowsDrive(path: $this->path); + $otherRoot = $this->_getWindowsDrive(path: $other->path); if ($thisRoot !== $otherRoot) { return $this; @@ -294,7 +294,7 @@ public function relativeTo(self $other): self // Find the common prefix $commonLength = 0; - $minLength = \min(\count($thisParts), \count($otherParts)); + $minLength = \min(\count(value: $thisParts), \count(value: $otherParts)); while ($commonLength < $minLength && $thisParts[$commonLength] === $otherParts[$commonLength]) { $commonLength++; @@ -304,21 +304,21 @@ public function relativeTo(self $other): self $relParts = []; // Add '..' for each directory level to go up - $upCount = \count($otherParts) - $commonLength; + $upCount = \count(value: $otherParts) - $commonLength; if ($upCount > 0) { - $relParts = \array_fill(0, $upCount, '..'); + $relParts = \array_fill(start_index: 0, count: $upCount, value: '..'); } // Add path components to go down - if ($commonLength < \count($thisParts)) { - $relParts = [...$relParts, ...\array_slice($thisParts, $commonLength)]; + if ($commonLength < \count(value: $thisParts)) { + $relParts = [...$relParts, ...\array_slice(array: $thisParts, offset: $commonLength)]; } if (empty($relParts)) { return self::create('.'); } - return self::create(\implode(self::getDirectorySeparator(), $relParts)); + return self::create(\implode(separator: self::getDirectorySeparator(), array: $relParts)); } /** @@ -338,7 +338,7 @@ public function absolute(): self */ public function trim(string $path): self { - return self::create(\substr(\str_replace($path, '', $this->toString()), 1)); + return self::create(\substr(string: \str_replace(search: $path, replace: '', subject: $this->toString()), offset: 1)); } /** @@ -362,11 +362,11 @@ private static function _isAbsolute(string $path): bool // Windows absolute path if (self::getDirectorySeparator() === '\\') { // Drive letter, UNC path, or absolute path - return (bool) \preg_match('~^(?:[a-zA-Z]:(?:\\\\|/)|\\\\\\\\|/)~', $path); + return (bool) \preg_match(pattern: '~^(?:[a-zA-Z]:(?:\\\\|/)|\\\\\\\\|/)~', subject: $path); } // Unix-like absolute path - return \str_starts_with($path, '/'); + return \str_starts_with(haystack: $path, needle: '/'); } /** @@ -375,13 +375,13 @@ private static function _isAbsolute(string $path): bool private static function normalizePath(string $path): string { // Normalize directory separators - $path = \str_replace(['\\', '/'], self::getDirectorySeparator(), $path); + $path = \str_replace(search: ['\\', '/'], replace: self::getDirectorySeparator(), subject: $path); // Normalize multiple separators $path = \preg_replace( - '~' . \preg_quote(self::getDirectorySeparator(), '~') . '{2,}~', - self::getDirectorySeparator(), - $path, + pattern: '~' . \preg_quote(str: self::getDirectorySeparator(), delimiter: '~') . '{2,}~', + replacement: self::getDirectorySeparator(), + subject: $path, ); // Empty path becomes current directory @@ -392,9 +392,9 @@ private static function normalizePath(string $path): string // Extract Windows drive letter if present $driveLetter = ''; $isWindowsPath = false; - if (self::getDirectorySeparator() === '\\' && \preg_match('~^([a-zA-Z]:)~', (string) $path, $matches) === 1) { + if (self::getDirectorySeparator() === '\\' && \preg_match(pattern: '~^([a-zA-Z]:)~', subject: (string) $path, matches: $matches) === 1) { $driveLetter = $matches[1]; - $path = \substr((string) $path, 2); // Remove drive letter for normalization + $path = \substr(string: (string) $path, offset: 2); // Remove drive letter for normalization $isWindowsPath = true; } @@ -406,8 +406,8 @@ private static function normalizePath(string $path): string * @psalm-suppress RedundantCast */ $parts = \array_filter( - \explode(self::getDirectorySeparator(), (string) $path), - static fn($part) => $part !== '', + array: \explode(separator: self::getDirectorySeparator(), string: (string) $path), + callback: static fn($part) => $part !== '', ); $result = []; @@ -418,7 +418,7 @@ private static function normalizePath(string $path): string if ($part === '..') { if (!empty($result)) { - \array_pop($result); + \array_pop(array: $result); } elseif (!$isAbsolute) { $result[] = '..'; } @@ -429,7 +429,7 @@ private static function normalizePath(string $path): string } // Reconstruct the path - $normalizedPath = \implode(self::getDirectorySeparator(), $result); + $normalizedPath = \implode(separator: self::getDirectorySeparator(), array: $result); // Handle Windows paths specifically if ($isWindowsPath) { @@ -464,7 +464,7 @@ private function isRoot(): bool } // Windows root (C:\ or similar) - if (self::getDirectorySeparator() === '\\' && \preg_match('~^[a-zA-Z]:[\\\\/]?$~', $normalized)) { + if (self::getDirectorySeparator() === '\\' && \preg_match(pattern: '~^[a-zA-Z]:[\\\\/]?$~', subject: $normalized)) { return true; } @@ -476,7 +476,7 @@ private function isRoot(): bool */ private function _getWindowsDrive(string $path): string { - if (\preg_match('~^([a-zA-Z]:)~', $path, $matches)) { + if (\preg_match(pattern: '~^([a-zA-Z]:)~', subject: $path, matches: $matches)) { return $matches[1]; } diff --git a/src/Application/Kernel.php b/src/Application/Kernel.php index 6d7cd085..81a6872b 100644 --- a/src/Application/Kernel.php +++ b/src/Application/Kernel.php @@ -54,8 +54,8 @@ protected function __construct( parent::__construct($container, $exceptionHandler, $bootloader, $directories); $container->bindSingleton( - DirectoriesInterface::class, - new Directories($this->mapDirectories($directories)), + alias: DirectoriesInterface::class, + resolver: new Directories(directories: $this->mapDirectories(directories: $directories)), ); } @@ -126,7 +126,7 @@ protected function bootstrap(): void {} protected function mapDirectories(array $directories): array { if (!isset($directories['root'])) { - throw new BootException('Missing required directory `root`'); + throw new BootException(message: 'Missing required directory `root`'); } return \array_merge( diff --git a/src/Application/Logger/ConsoleLogger.php b/src/Application/Logger/ConsoleLogger.php index df723a66..df01ce92 100644 --- a/src/Application/Logger/ConsoleLogger.php +++ b/src/Application/Logger/ConsoleLogger.php @@ -31,17 +31,17 @@ public function getPrefix(): string public function log($level, string|\Stringable $message, array $context = []): void { - $logLevel = $this->normalizeLogLevel($level); + $logLevel = $this->normalizeLogLevel(level: $level); // Only output if verbosity of the output is sufficient for this log level - if (!$this->isLevelEnabled($logLevel)) { + if (!$this->isLevelEnabled(level: $logLevel)) { return; } $formattedMessage = $this->formatter->format($logLevel, $message, $context); // Apply color formatting based on log level - $colorizedMessage = $this->colorize($formattedMessage, $logLevel); + $colorizedMessage = $this->colorize(message: $formattedMessage, level: $logLevel); $this->output->writeln($colorizedMessage); } @@ -75,7 +75,7 @@ private function isLevelEnabled(string $level): bool */ private function colorize(string $message, string $level): string { - $color = LogLevel::fromString($level)->getAnsiColor(); + $color = LogLevel::fromString(level: $level)->getAnsiColor(); if (empty($color)) { return $message; @@ -89,12 +89,12 @@ private function colorize(string $message, string $level): string */ private function normalizeLogLevel(mixed $level): string { - if (\is_string($level)) { - return \strtolower($level); + if (\is_string(value: $level)) { + return \strtolower(string: $level); } if ($level instanceof \Stringable) { - return \strtolower((string) $level); + return \strtolower(string: (string) $level); } // Default to 'info' for invalid levels diff --git a/src/Application/Logger/FileLogger.php b/src/Application/Logger/FileLogger.php index e22b7f1d..36f43bca 100644 --- a/src/Application/Logger/FileLogger.php +++ b/src/Application/Logger/FileLogger.php @@ -39,7 +39,7 @@ public function withPrefix(string $prefix): self } $this->pushProcessor( - (new TagProcessor())->addTags([$prefix]), + callback: (new TagProcessor())->addTags(tags: [$prefix]), ); return $this; diff --git a/src/Application/Logger/LogLevel.php b/src/Application/Logger/LogLevel.php index c719b8f2..bb075cc8 100644 --- a/src/Application/Logger/LogLevel.php +++ b/src/Application/Logger/LogLevel.php @@ -25,7 +25,7 @@ enum LogLevel: string */ public static function fromString(string $level): self { - $normalizedLevel = \strtolower($level); + $normalizedLevel = \strtolower(string: $level); return match ($normalizedLevel) { PsrLogLevel::EMERGENCY => self::EMERGENCY, @@ -59,6 +59,6 @@ public function getAnsiColor(): string */ public function getLabel(): string { - return \strtoupper($this->value); + return \strtoupper(string: $this->value); } } diff --git a/src/Application/Logger/SimpleFormatter.php b/src/Application/Logger/SimpleFormatter.php index cd7d61b1..d25335fa 100644 --- a/src/Application/Logger/SimpleFormatter.php +++ b/src/Application/Logger/SimpleFormatter.php @@ -35,17 +35,17 @@ public function __construct( */ public function format(string $level, string|\Stringable $message, array $context = []): string { - $logLevel = LogLevel::fromString($level); + $logLevel = LogLevel::fromString(level: $level); $formattedMessage = (string) $message; // Interpolate placeholders in the message - $formattedMessage = $this->interpolate($formattedMessage, $context); + $formattedMessage = $this->interpolate(message: $formattedMessage, context: $context); // Build the complete formatted line $parts = []; if ($this->includeTimestamp) { - $parts[] = '[' . \date($this->dateFormat) . ']'; + $parts[] = '[' . \date(format: $this->dateFormat) . ']'; } $parts[] = '[' . $logLevel->getLabel() . ']'; @@ -55,7 +55,7 @@ public function format(string $level, string|\Stringable $message, array $contex $parts[] = $formattedMessage; - return ' ' . \implode(' ', $parts); + return ' ' . \implode(separator: ' ', array: $parts); } public function withPrefix(string $prefix): static @@ -74,7 +74,7 @@ public function getPrefix(): string public function log($level, \Stringable|string $message, array $context = []): void { - echo $this->format($level, $message, $context); + echo $this->format(level: $level, message: $message, context: $context); } /** @@ -93,9 +93,9 @@ private function interpolate(string $message, array $context): string return $message; } - $json = \json_encode($context, \JSON_PRETTY_PRINT); + $json = \json_encode(value: $context, flags: \JSON_PRETTY_PRINT); // add indentation fo each line - $json = \preg_replace('/^/m', ' ', $json); + $json = \preg_replace(pattern: '/^/m', replacement: ' ', subject: $json); return $message . "\n\n" . $json . "\n"; } diff --git a/src/Config/ConfigLoaderBootloader.php b/src/Config/ConfigLoaderBootloader.php index 2959fb66..da3d80ec 100644 --- a/src/Config/ConfigLoaderBootloader.php +++ b/src/Config/ConfigLoaderBootloader.php @@ -75,7 +75,7 @@ public function defineSingletons(): array ParserPluginRegistry::class => fn( ImportParserPlugin $importParserPlugin, DocumentsParserPlugin $documentsParserPlugin, - ) => new ParserPluginRegistry([ + ) => new ParserPluginRegistry(plugins: [ // todo: think about priority when registering plugins ...$this->parserPlugins, $documentsParserPlugin, @@ -112,7 +112,7 @@ interface: ConfigLoaderInterface::class, ConfigMergerRegistry $registry, ) { foreach ($this->mergers as $merger) { - $registry->register($merger); + $registry->register(merger: $merger); } return $registry; @@ -124,7 +124,7 @@ public function init( DocumentConfigMerger $documentConfigMerger, VariablesConfigMerger $variablesConfigMerger, ): void { - $this->registerMerger($documentConfigMerger); - $this->registerMerger($variablesConfigMerger); + $this->registerMerger(merger: $documentConfigMerger); + $this->registerMerger(merger: $variablesConfigMerger); } } diff --git a/src/Config/ConfigType.php b/src/Config/ConfigType.php index a8d33a21..a315bb86 100644 --- a/src/Config/ConfigType.php +++ b/src/Config/ConfigType.php @@ -17,8 +17,8 @@ enum ConfigType: string public static function types(): array { return \array_map( - static fn(self $type) => $type->value, - self::cases(), + callback: static fn(self $type) => $type->value, + array: self::cases(), ); } @@ -28,7 +28,7 @@ public static function fromExtension(string $ext): self 'json' => self::Json, 'yaml', 'yml' => self::Yaml, 'php' => self::PHP, - default => throw new \ValueError(\sprintf('Unsupported config type: %s', $ext)), + default => throw new \ValueError(message: \sprintf('Unsupported config type: %s', $ext)), }; } } diff --git a/src/Config/ConfigurationProvider.php b/src/Config/ConfigurationProvider.php index 7efeb62c..a32f8f8e 100644 --- a/src/Config/ConfigurationProvider.php +++ b/src/Config/ConfigurationProvider.php @@ -41,7 +41,7 @@ public function fromString(string $jsonConfig): ConfigLoaderInterface */ public function fromPath(string $configPath): ConfigLoaderInterface { - $resolvedPath = $this->resolvePath($configPath); + $resolvedPath = $this->resolvePath(path: $configPath); if ($resolvedPath->isDir()) { $this->logger?->info('Looking for configuration files in directory', [ @@ -74,7 +74,7 @@ public function fromDefaultLocation(): ConfigLoaderInterface */ private function resolvePath(string $path): FSPath { - $pathObj = FSPath::create($path); + $pathObj = FSPath::create(path: $path); // If it's an absolute path, use it directly if ($pathObj->isAbsolute()) { @@ -86,7 +86,7 @@ private function resolvePath(string $path): FSPath // Check if the path exists if (!$resolvedPath->exists()) { - throw new ConfigLoaderException(\sprintf('Path not found: %s', $resolvedPath)); + throw new ConfigLoaderException(message: \sprintf('Path not found: %s', $resolvedPath)); } return $resolvedPath; diff --git a/src/Config/Exclude/AbstractExclusion.php b/src/Config/Exclude/AbstractExclusion.php index 7974a420..765c33b7 100644 --- a/src/Config/Exclude/AbstractExclusion.php +++ b/src/Config/Exclude/AbstractExclusion.php @@ -34,9 +34,9 @@ abstract public function matches(string $path): bool; */ protected function normalizePattern(string $pattern): string { - $pattern = \preg_replace('#^\./#', '', $pattern); + $pattern = \preg_replace(pattern: '#^\./#', replacement: '', subject: $pattern); // Remove trailing slash - return \rtrim((string) $pattern, '/'); + return \rtrim(string: (string) $pattern, characters: '/'); } } diff --git a/src/Config/Exclude/ExcludeBootloader.php b/src/Config/Exclude/ExcludeBootloader.php index dd8b9e1a..7230680b 100644 --- a/src/Config/Exclude/ExcludeBootloader.php +++ b/src/Config/Exclude/ExcludeBootloader.php @@ -22,6 +22,6 @@ public function defineSingletons(): array public function boot(ConfigLoaderBootloader $configLoader, ExcludeParserPlugin $excludeParser): void { // Register the exclude parser plugin - $configLoader->registerParserPlugin($excludeParser); + $configLoader->registerParserPlugin(plugin: $excludeParser); } } diff --git a/src/Config/Exclude/ExcludeParserPlugin.php b/src/Config/Exclude/ExcludeParserPlugin.php index 3e86f69f..f0eb585a 100644 --- a/src/Config/Exclude/ExcludeParserPlugin.php +++ b/src/Config/Exclude/ExcludeParserPlugin.php @@ -27,30 +27,30 @@ public function getConfigKey(): string public function supports(array $config): bool { - return isset($config['exclude']) && \is_array($config['exclude']); + return isset($config['exclude']) && \is_array(value: $config['exclude']); } public function parse(array $config, string $rootPath): ?RegistryInterface { - if (!$this->supports($config)) { + if (!$this->supports(config: $config)) { return null; } - \assert($this->registry instanceof RegistryInterface); + \assert(assertion: $this->registry instanceof RegistryInterface); $excludeConfig = $config['exclude']; // Parse patterns - if (isset($excludeConfig['patterns']) && \is_array($excludeConfig['patterns'])) { - $this->parsePatterns($excludeConfig['patterns']); + if (isset($excludeConfig['patterns']) && \is_array(value: $excludeConfig['patterns'])) { + $this->parsePatterns(patterns: $excludeConfig['patterns']); } // Parse paths - if (isset($excludeConfig['paths']) && \is_array($excludeConfig['paths'])) { - $this->parsePaths($excludeConfig['paths']); + if (isset($excludeConfig['paths']) && \is_array(value: $excludeConfig['paths'])) { + $this->parsePaths(paths: $excludeConfig['paths']); } $this->logger?->info('Parsed exclusion configuration', [ - 'patternCount' => \count($this->registry->getPatterns()), + 'patternCount' => \count(value: $this->registry->getPatterns()), ]); return $this->registry; @@ -68,14 +68,14 @@ public function updateConfig(array $config, string $rootPath): array private function parsePatterns(array $patterns): void { foreach ($patterns as $pattern) { - if (!\is_string($pattern) || empty($pattern)) { + if (!\is_string(value: $pattern) || empty($pattern)) { $this->logger?->warning('Invalid exclusion pattern, skipping', [ 'pattern' => $pattern, ]); continue; } - $this->registry->addPattern(new PatternExclusion($pattern)); + $this->registry->addPattern(new PatternExclusion(pattern: $pattern)); } } @@ -85,14 +85,14 @@ private function parsePatterns(array $patterns): void private function parsePaths(array $paths): void { foreach ($paths as $path) { - if (!\is_string($path) || empty($path)) { + if (!\is_string(value: $path) || empty($path)) { $this->logger?->warning('Invalid exclusion path, skipping', [ 'path' => $path, ]); continue; } - $this->registry->addPattern(new PathExclusion($path)); + $this->registry->addPattern(new PathExclusion(pattern: $path)); } } } diff --git a/src/Config/Exclude/ExcludeRegistry.php b/src/Config/Exclude/ExcludeRegistry.php index 94a47d6b..1023aabf 100644 --- a/src/Config/Exclude/ExcludeRegistry.php +++ b/src/Config/Exclude/ExcludeRegistry.php @@ -87,7 +87,7 @@ public function getItems(): array */ public function getIterator(): \Traversable { - return new \ArrayIterator($this->patterns); + return new \ArrayIterator(array: $this->patterns); } /** @@ -97,8 +97,8 @@ public function jsonSerialize(): array { return [ 'patterns' => \array_map( - static fn(ExclusionPatternInterface $pattern) => $pattern->jsonSerialize(), - $this->patterns, + callback: static fn(ExclusionPatternInterface $pattern) => $pattern->jsonSerialize(), + array: $this->patterns, ), ]; } diff --git a/src/Config/Exclude/PathExclusion.php b/src/Config/Exclude/PathExclusion.php index e578c365..a7875325 100644 --- a/src/Config/Exclude/PathExclusion.php +++ b/src/Config/Exclude/PathExclusion.php @@ -16,7 +16,7 @@ public function __construct(string $pattern) { parent::__construct($pattern); - $this->normalizedPattern = $this->normalizePattern($pattern); + $this->normalizedPattern = $this->normalizePattern(pattern: $pattern); } /** @@ -27,10 +27,10 @@ public function __construct(string $pattern) */ public function matches(string $path): bool { - $normalizedPath = $this->normalizePattern($path); + $normalizedPath = $this->normalizePattern(pattern: $path); return $normalizedPath === $this->normalizedPattern || - \str_contains($normalizedPath, $this->normalizedPattern); + \str_contains(haystack: $normalizedPath, needle: $this->normalizedPattern); } public function jsonSerialize(): array diff --git a/src/Config/Exclude/PatternExclusion.php b/src/Config/Exclude/PatternExclusion.php index e7a3660f..9b2092cd 100644 --- a/src/Config/Exclude/PatternExclusion.php +++ b/src/Config/Exclude/PatternExclusion.php @@ -19,7 +19,7 @@ public function __construct(string $pattern) { parent::__construct($pattern); - $this->matcher = new PathMatcher($pattern); + $this->matcher = new PathMatcher(pattern: $pattern); } /** @@ -29,7 +29,7 @@ public function __construct(string $pattern) */ public function matches(string $path): bool { - return $this->matcher->isMatch($path); + return $this->matcher->isMatch(path: $path); } public function jsonSerialize(): array diff --git a/src/Config/Import/CircularImportDetector.php b/src/Config/Import/CircularImportDetector.php index 1351078d..6903b47f 100644 --- a/src/Config/Import/CircularImportDetector.php +++ b/src/Config/Import/CircularImportDetector.php @@ -19,7 +19,7 @@ final class CircularImportDetector implements CircularImportDetectorInterface */ public function wouldCreateCircularDependency(string $path): bool { - return \in_array($path, $this->importStack, true); + return \in_array(needle: $path, haystack: $this->importStack, strict: true); } /** @@ -27,12 +27,12 @@ public function wouldCreateCircularDependency(string $path): bool */ public function beginProcessing(string $path): void { - if ($this->wouldCreateCircularDependency($path)) { + if ($this->wouldCreateCircularDependency(path: $path)) { throw new \RuntimeException( - \sprintf( + message: \sprintf( 'Circular import detected: %s is already being processed. Import stack: %s', $path, - \implode(' -> ', $this->importStack), + \implode(separator: ' -> ', array: $this->importStack), ), ); } @@ -46,10 +46,10 @@ public function beginProcessing(string $path): void public function endProcessing(string $path): void { // Find the path in the stack and remove it and anything after it - $index = \array_search($path, $this->importStack, true); + $index = \array_search(needle: $path, haystack: $this->importStack, strict: true); if ($index !== false) { - \array_splice($this->importStack, $index); + \array_splice(array: $this->importStack, offset: $index); } } } diff --git a/src/Config/Import/ImportParserPlugin.php b/src/Config/Import/ImportParserPlugin.php index a2b69524..8605406e 100644 --- a/src/Config/Import/ImportParserPlugin.php +++ b/src/Config/Import/ImportParserPlugin.php @@ -42,7 +42,7 @@ public function supports(array $config): bool public function updateConfig(array $config, string $rootPath): array { // If no imports, return the original config - if (!$this->supports($config)) { + if (!$this->supports(config: $config)) { return $config; } @@ -50,7 +50,7 @@ public function updateConfig(array $config, string $rootPath): array return $config; } - if (!\is_array($config['import'])) { + if (!\is_array(value: $config['import'])) { $this->logger?->warning('Invalid import configuration', [ 'config' => $config['import'], ]); @@ -60,14 +60,14 @@ public function updateConfig(array $config, string $rootPath): array $this->logger?->debug('Processing imports', [ 'rootPath' => $rootPath, - 'importCount' => \count($config['import']), + 'importCount' => \count(value: $config['import']), ]); // Process imports and return the merged configuration - $processedConfig = $this->importResolver->resolveImports($config, $rootPath); + $processedConfig = $this->importResolver->resolveImports(config: $config, basePath: $rootPath); foreach ($processedConfig->imports as $import) { - $this->registry->register($import); + $this->registry->register(import: $import); } $this->logger?->debug('Imports processed successfully'); diff --git a/src/Config/Import/ImportRegistry.php b/src/Config/Import/ImportRegistry.php index 6f684129..1d612505 100644 --- a/src/Config/Import/ImportRegistry.php +++ b/src/Config/Import/ImportRegistry.php @@ -46,6 +46,6 @@ public function jsonSerialize(): array public function getIterator(): \Traversable { - return new \ArrayIterator($this->getItems()); + return new \ArrayIterator(array: $this->getItems()); } } diff --git a/src/Config/Import/ImportResolver.php b/src/Config/Import/ImportResolver.php index 046769d7..89c2e98b 100644 --- a/src/Config/Import/ImportResolver.php +++ b/src/Config/Import/ImportResolver.php @@ -51,8 +51,8 @@ public function resolveImports(array $config, string $basePath, array &$parsedIm } $imports = $config['import']; - if (!\is_array($imports)) { - throw new ConfigLoaderException('The "import" property must be an array'); + if (!\is_array(value: $imports)) { + throw new ConfigLoaderException(message: 'The "import" property must be an array'); } // Process each import @@ -60,15 +60,15 @@ public function resolveImports(array $config, string $basePath, array &$parsedIm $importedConfigs = []; foreach ($imports as $importConfig) { // Create source configuration from the raw import config - $sourceConfig = $this->sourceConfigFactory->createFromArray($importConfig, $basePath); + $sourceConfig = $this->sourceConfigFactory->createFromArray(config: $importConfig, basePath: $basePath); // Handle wildcard paths (only for local sources) if ($sourceConfig instanceof LocalSourceConfig && $sourceConfig->hasWildcard()) { $this->processWildcardImport( - $sourceConfig, - $basePath, - $parsedImports, - $importedConfigs, + sourceConfig: $sourceConfig, + basePath: $basePath, + parsedImports: $parsedImports, + importedConfigs: $importedConfigs, ); continue; } @@ -76,7 +76,7 @@ public function resolveImports(array $config, string $basePath, array &$parsedIm // For local imports, check if already processed if ($sourceConfig instanceof LocalSourceConfig) { $absolutePath = $sourceConfig->getAbsolutePath(); - if (\in_array($absolutePath, $parsedImports, true)) { + if (\in_array(needle: $absolutePath, haystack: $parsedImports, strict: true)) { $this->logger?->debug('Skipping already processed import', [ 'path' => $sourceConfig->getPath(), 'type' => $sourceConfig->getType(), @@ -87,10 +87,10 @@ public function resolveImports(array $config, string $basePath, array &$parsedIm // Process a single import $this->processSingleImport( - $sourceConfig, - $basePath, - $parsedImports, - $importedConfigs, + sourceConfig: $sourceConfig, + basePath: $basePath, + parsedImports: $parsedImports, + importedConfigs: $importedConfigs, ); } @@ -100,8 +100,8 @@ public function resolveImports(array $config, string $basePath, array &$parsedIm return new ResolvedConfig( config: $this->configMergerProvider->mergeConfigurations($config, ...$importedConfigs), imports: \array_map( - static fn(ImportedConfig $config) => $config->sourceConfig, - $importedConfigs, + callback: static fn(ImportedConfig $config) => $config->sourceConfig, + array: $importedConfigs, ), ); } @@ -116,7 +116,7 @@ private function processWildcardImport( array &$importedConfigs, ): void { // Find all files that match the pattern - $matchingPaths = $this->pathFinder->findMatchingPaths($sourceConfig->getPath(), $basePath); + $matchingPaths = $this->pathFinder->findMatchingPaths(pattern: $sourceConfig->getPath(), basePath: $basePath); if (empty($matchingPaths)) { $this->logger?->warning('No files match the wildcard pattern', [ @@ -128,14 +128,14 @@ private function processWildcardImport( $this->logger?->debug('Found files matching wildcard pattern', [ 'pattern' => $sourceConfig->getPath(), - 'count' => \count($matchingPaths), + 'count' => \count(value: $matchingPaths), 'paths' => $matchingPaths, ]); // Process each matching file foreach ($matchingPaths as $matchingPath) { // Skip if already processed - if (\in_array($matchingPath, $parsedImports, true)) { + if (\in_array(needle: $matchingPath, haystack: $parsedImports, strict: true)) { $this->logger?->debug('Skipping already processed wildcard match', [ 'path' => $matchingPath, ]); @@ -146,7 +146,7 @@ private function processWildcardImport( // Create a local source config for this match $localConfig = new LocalSourceConfig( - path: \ltrim(\str_replace($rootPathStr, '', $matchingPath), '/'), + path: \ltrim(string: \str_replace(search: $rootPathStr, replace: '', subject: $matchingPath), characters: '/'), absolutePath: $matchingPath, hasWildcard: false, pathPrefix: $sourceConfig->getPathPrefix(), @@ -155,10 +155,10 @@ private function processWildcardImport( // Process it using the standard import logic $this->processSingleImport( - $localConfig, - \dirname($matchingPath), // Base path is the directory of the matched file - $parsedImports, - $importedConfigs, + sourceConfig: $localConfig, + basePath: \dirname(path: $matchingPath), // Base path is the directory of the matched file + parsedImports: $parsedImports, + importedConfigs: $importedConfigs, ); } } @@ -183,11 +183,11 @@ private function processSingleImport( try { // Find an appropriate import source using the provider - $importSource = $this->sourceProvider->findSourceForConfig($sourceConfig); + $importSource = $this->sourceProvider->findSourceForConfig(config: $sourceConfig); if (!$importSource) { throw new ImportSourceException( - \sprintf( + message: \sprintf( 'No import source found for type "%s" and path "%s"', $sourceConfig->getType(), $sourceConfig->getPath(), @@ -207,9 +207,9 @@ private function processSingleImport( // Recursively process nested imports $importedConfig = $this->resolveImports( - $importedConfig, - $importBasePath, - $parsedImports, + config: $importedConfig, + basePath: $importBasePath, + parsedImports: $parsedImports, ); // Apply source path prefix for local imports @@ -217,16 +217,16 @@ private function processSingleImport( if ($sourceConfig->getPathPrefix() !== null) { $importedConfig = new ResolvedConfig( config: $this->documentPrefixer->applyPrefix( - $importedConfig->config, - $sourceConfig->getPathPrefix(), + config: $importedConfig->config, + pathPrefix: $sourceConfig->getPathPrefix(), ), imports: $importedConfig->imports, ); } $importedConfig = new ResolvedConfig( config: $this->sourcePrefixer->applyPrefix( - $importedConfig->config, - $sourceConfig->getConfigDirectory(), + config: $importedConfig->config, + pathPrefix: $sourceConfig->getConfigDirectory(), ), imports: $importedConfig->imports, ); diff --git a/src/Config/Import/Merger/AbstractConfigMerger.php b/src/Config/Import/Merger/AbstractConfigMerger.php index 7cbe0960..ebcba8c5 100644 --- a/src/Config/Import/Merger/AbstractConfigMerger.php +++ b/src/Config/Import/Merger/AbstractConfigMerger.php @@ -16,27 +16,27 @@ public function __construct( public function merge(array $mainConfig, ImportedConfig $importedConfig): array { // Skip if this merger doesn't support the configuration - if (!$this->supports($importedConfig)) { + if (!$this->supports(config: $importedConfig)) { return $mainConfig; } $configKey = $this->getConfigKey(); // Skip if the imported configuration doesn't contain this key - if (!isset($importedConfig[$configKey]) || !\is_array($importedConfig[$configKey])) { + if (!isset($importedConfig[$configKey]) || !\is_array(value: $importedConfig[$configKey])) { return $mainConfig; } // Initialize the config section if it doesn't exist - if (!isset($mainConfig[$configKey]) || !\is_array($mainConfig[$configKey])) { + if (!isset($mainConfig[$configKey]) || !\is_array(value: $mainConfig[$configKey])) { $mainConfig[$configKey] = []; } // Perform the actual merge $mainConfig[$configKey] = $this->performMerge( - $mainConfig[$configKey], - $importedConfig[$configKey], - $importedConfig, + mainSection: $mainConfig[$configKey], + importedSection: $importedConfig[$configKey], + importedConfig: $importedConfig, ); return $mainConfig; @@ -45,7 +45,7 @@ public function merge(array $mainConfig, ImportedConfig $importedConfig): array public function supports(ImportedConfig $config): bool { $configKey = $this->getConfigKey(); - return isset($config[$configKey]) && \is_array($config[$configKey]); + return isset($config[$configKey]) && \is_array(value: $config[$configKey]); } /** diff --git a/src/Config/Import/PathMatcher.php b/src/Config/Import/PathMatcher.php index 6be57c21..194c22eb 100644 --- a/src/Config/Import/PathMatcher.php +++ b/src/Config/Import/PathMatcher.php @@ -16,7 +16,7 @@ */ public function __construct(private string $pattern) { - $this->regex = $this->isRegex($this->pattern) ? $this->pattern : $this->globToRegex($this->pattern); + $this->regex = $this->isRegex(str: $this->pattern) ? $this->pattern : $this->globToRegex(pattern: $this->pattern); } /** @@ -24,8 +24,8 @@ public function __construct(private string $pattern) */ public static function containsWildcard(string $path): bool { - return \str_contains($path, '*') || \str_contains($path, '?') || - \str_contains($path, '[') || \str_contains($path, '{'); + return \str_contains(haystack: $path, needle: '*') || \str_contains(haystack: $path, needle: '?') || + \str_contains(haystack: $path, needle: '[') || \str_contains(haystack: $path, needle: '{'); } /** @@ -33,7 +33,7 @@ public static function containsWildcard(string $path): bool */ public function isMatch(string $path): bool { - return (bool) \preg_match($this->regex, $path); + return (bool) \preg_match(pattern: $this->regex, subject: $path); } /** @@ -72,7 +72,7 @@ private function globToRegex(string $pattern): string // Start at the beginning of the string $regex = '~^'; - $length = \strlen($pattern); + $length = \strlen(string: $pattern); for ($i = 0; $i < $length; $i++) { $char = $pattern[$i]; $nextChar = $i + 1 < $length ? $pattern[$i + 1] : null; @@ -90,7 +90,7 @@ private function globToRegex(string $pattern): string // If we are escaping, add the escaped character if ($escaping) { - $regex .= \preg_quote($char, '~'); + $regex .= \preg_quote(str: $char, delimiter: '~'); $escaping = false; continue; } @@ -114,7 +114,7 @@ private function globToRegex(string $pattern): string } elseif ($char === ',') { $regex .= '|'; } else { - $regex .= \preg_quote($char, '~'); + $regex .= \preg_quote(str: $char, delimiter: '~'); } continue; } @@ -176,12 +176,12 @@ private function isRegex(string $str): bool { $availableModifiers = 'imsxuADUn'; - if (\preg_match('/^(.{3,}?)[' . $availableModifiers . ']*$/', $str, $m)) { - $start = \substr($m[1], 0, 1); - $end = \substr($m[1], -1); + if (\preg_match(pattern: '/^(.{3,}?)[' . $availableModifiers . ']*$/', subject: $str, matches: $m)) { + $start = \substr(string: $m[1], offset: 0, length: 1); + $end = \substr(string: $m[1], offset: -1); if ($start === $end) { - return !\preg_match('/[*?[:alnum:] \\\\]/', $start); + return !\preg_match(pattern: '/[*?[:alnum:] \\\\]/', subject: $start); } foreach ([['{', '}'], ['(', ')'], ['[', ']'], ['<', '>']] as $delimiters) { diff --git a/src/Config/Import/PathPrefixer/DocumentOutputPathPrefixer.php b/src/Config/Import/PathPrefixer/DocumentOutputPathPrefixer.php index f5e573aa..cd79c69c 100644 --- a/src/Config/Import/PathPrefixer/DocumentOutputPathPrefixer.php +++ b/src/Config/Import/PathPrefixer/DocumentOutputPathPrefixer.php @@ -23,10 +23,10 @@ public function applyPrefix(array $config, string $pathPrefix): array { // Apply to document outputPath values - if (isset($config['documents']) && \is_array($config['documents'])) { + if (isset($config['documents']) && \is_array(value: $config['documents'])) { foreach ($config['documents'] as &$document) { if (isset($document['outputPath'])) { - $document['outputPath'] = $this->combinePaths($pathPrefix, $document['outputPath']); + $document['outputPath'] = $this->combinePaths(prefix: $pathPrefix, path: $document['outputPath']); } } } diff --git a/src/Config/Import/PathPrefixer/PathPrefixer.php b/src/Config/Import/PathPrefixer/PathPrefixer.php index e709ab4e..f9ff10ba 100644 --- a/src/Config/Import/PathPrefixer/PathPrefixer.php +++ b/src/Config/Import/PathPrefixer/PathPrefixer.php @@ -19,8 +19,8 @@ abstract public function applyPrefix(array $config, string $pathPrefix): array; */ protected function combinePaths(string $prefix, string $path): string { - $combined = \rtrim($prefix, '/') . '/' . \ltrim($path, '/'); - return $this->normalizePath($combined); + $combined = \rtrim(string: $prefix, characters: '/') . '/' . \ltrim(string: $path, characters: '/'); + return $this->normalizePath(path: $combined); } /** @@ -28,7 +28,7 @@ protected function combinePaths(string $prefix, string $path): string */ protected function isAbsolutePath(string $path): bool { - return \str_starts_with($path, '/'); + return \str_starts_with(haystack: $path, needle: '/'); } /** @@ -42,13 +42,13 @@ protected function normalizePath(string $path): string } // Preserve leading slash for absolute paths - $isAbsolute = $this->isAbsolutePath($path); + $isAbsolute = $this->isAbsolutePath(path: $path); // Replace backslashes with forward slashes for consistency - $path = \str_replace('\\', '/', $path); + $path = \str_replace(search: '\\', replace: '/', subject: $path); // Split the path into segments - $segments = \explode('/', $path); + $segments = \explode(separator: '/', string: $path); // Process each segment $result = []; @@ -60,8 +60,8 @@ protected function normalizePath(string $path): string if ($segment === '..') { // Handle parent directory references by removing the last segment - if (!empty($result) && $result[\count($result) - 1] !== '..') { - \array_pop($result); + if (!empty($result) && $result[\count(value: $result) - 1] !== '..') { + \array_pop(array: $result); } else { // If no segments to pop, preserve the .. reference $result[] = $segment; @@ -73,7 +73,7 @@ protected function normalizePath(string $path): string } // Combine the segments - $normalized = \implode('/', $result); + $normalized = \implode(separator: '/', array: $result); // Restore leading slash for absolute paths if ($isAbsolute && !empty($normalized)) { diff --git a/src/Config/Import/PathPrefixer/SourcePathPrefixer.php b/src/Config/Import/PathPrefixer/SourcePathPrefixer.php index 102ef3e9..7264cb61 100644 --- a/src/Config/Import/PathPrefixer/SourcePathPrefixer.php +++ b/src/Config/Import/PathPrefixer/SourcePathPrefixer.php @@ -19,11 +19,11 @@ public function applyPrefix(array $config, string $pathPrefix): array { // Apply to documents array - if (isset($config['documents']) && \is_array($config['documents'])) { + if (isset($config['documents']) && \is_array(value: $config['documents'])) { foreach ($config['documents'] as &$document) { - if (isset($document['sources']) && \is_array($document['sources'])) { + if (isset($document['sources']) && \is_array(value: $document['sources'])) { foreach ($document['sources'] as &$source) { - $source = $this->applyPathPrefixToSource($source, $pathPrefix); + $source = $this->applyPathPrefixToSource(source: $source, prefix: $pathPrefix); } } } @@ -39,13 +39,13 @@ private function applyPathPrefixToSource(array $source, string $prefix): array { // Handle sourcePaths property if (isset($source['sourcePaths'])) { - $source['sourcePaths'] = $this->applyPrefixToPaths($source['sourcePaths'], $prefix); + $source['sourcePaths'] = $this->applyPrefixToPaths(paths: $source['sourcePaths'], prefix: $prefix); } // Handle composerPath property (for composer source) if (isset($source['composerPath']) && $source['type'] === 'composer') { - if (!$this->isAbsolutePath($source['composerPath'])) { - $source['composerPath'] = $this->combinePaths($prefix, $source['composerPath']); + if (!$this->isAbsolutePath(path: $source['composerPath'])) { + $source['composerPath'] = $this->combinePaths(prefix: $prefix, path: $source['composerPath']); } } @@ -57,18 +57,18 @@ private function applyPathPrefixToSource(array $source, string $prefix): array */ private function applyPrefixToPaths(mixed $paths, string $prefix): mixed { - if (\is_string($paths)) { + if (\is_string(value: $paths)) { // Skip absolute paths - if ($this->isAbsolutePath($paths)) { + if ($this->isAbsolutePath(path: $paths)) { return $paths; } - return $this->combinePaths($prefix, $paths); + return $this->combinePaths(prefix: $prefix, path: $paths); } - if (\is_array($paths)) { + if (\is_array(value: $paths)) { $result = []; foreach ($paths as $path) { - $result[] = $this->applyPrefixToPaths($path, $prefix); + $result[] = $this->applyPrefixToPaths(paths: $path, prefix: $prefix); } return $result; } diff --git a/src/Config/Import/Source/AbstractImportSource.php b/src/Config/Import/Source/AbstractImportSource.php index 6b91826f..d2d99eab 100644 --- a/src/Config/Import/Source/AbstractImportSource.php +++ b/src/Config/Import/Source/AbstractImportSource.php @@ -36,7 +36,7 @@ protected function readConfig(string $path, ReaderInterface $reader): array ]); throw new Exception\ImportSourceException( - \sprintf('Unsupported configuration file format: %s', $path), + message: \sprintf('Unsupported configuration file format: %s', $path), ); } @@ -48,7 +48,7 @@ protected function readConfig(string $path, ReaderInterface $reader): array */ protected function processSelectiveImports(array $config, SourceConfigInterface $sourceConfig): array { - $config = $this->filterConfigSections($config); + $config = $this->filterConfigSections(config: $config); if (!isset($config['documents']) || !$sourceConfig instanceof LocalSourceConfig) { return $config; @@ -57,7 +57,7 @@ protected function processSelectiveImports(array $config, SourceConfigInterface // If no specific docs are requested, return the full config $selectiveDocs = $sourceConfig->getSelectiveDocuments(); if (empty($selectiveDocs)) { - return $this->filterConfigSections($config); + return $this->filterConfigSections(config: $config); } $this->logger->debug('Processing selective imports', [ @@ -67,7 +67,7 @@ protected function processSelectiveImports(array $config, SourceConfigInterface ]); // For selective imports, we only include specific documents - if (isset($config['documents']) && \is_array($config['documents'])) { + if (isset($config['documents']) && \is_array(value: $config['documents'])) { $filteredDocuments = []; foreach ($config['documents'] as $document) { @@ -76,8 +76,8 @@ protected function processSelectiveImports(array $config, SourceConfigInterface $outputPath = $document['outputPath']; foreach ($selectiveDocs as $requestedDoc) { // Simple wildcard matching - $pattern = $this->wildcardToRegex($requestedDoc); - if (\preg_match($pattern, (string) $outputPath)) { + $pattern = $this->wildcardToRegex(pattern: $requestedDoc); + if (\preg_match(pattern: $pattern, subject: (string) $outputPath)) { $filteredDocuments[] = $document; break; } @@ -89,11 +89,11 @@ protected function processSelectiveImports(array $config, SourceConfigInterface $config['documents'] = $filteredDocuments; $this->logger->debug('Selective import processed', [ - 'totalDocuments' => \count($filteredDocuments), + 'totalDocuments' => \count(value: $filteredDocuments), ]); } - return $this->filterConfigSections($config); + return $this->filterConfigSections(config: $config); } /** @@ -101,9 +101,9 @@ protected function processSelectiveImports(array $config, SourceConfigInterface */ protected function wildcardToRegex(string $pattern): string { - $pattern = \preg_quote($pattern, '/'); - $pattern = \str_replace('\*', '.*', $pattern); - $pattern = \str_replace('\?', '.', $pattern); + $pattern = \preg_quote(str: $pattern, delimiter: '/'); + $pattern = \str_replace(search: '\*', replace: '.*', subject: $pattern); + $pattern = \str_replace(search: '\?', replace: '.', subject: $pattern); return '/^' . $pattern . '$/'; } diff --git a/src/Config/Import/Source/Config/AbstractSourceConfig.php b/src/Config/Import/Source/Config/AbstractSourceConfig.php index f50d1a0a..4d898775 100644 --- a/src/Config/Import/Source/Config/AbstractSourceConfig.php +++ b/src/Config/Import/Source/Config/AbstractSourceConfig.php @@ -41,6 +41,6 @@ public function getFilter(): ?FilterConfig public function getConfigDirectory(): string { - return \dirname($this->getPath()); + return \dirname(path: $this->getPath()); } } diff --git a/src/Config/Import/Source/Config/SourceConfigFactory.php b/src/Config/Import/Source/Config/SourceConfigFactory.php index 1309800b..ea728db8 100644 --- a/src/Config/Import/Source/Config/SourceConfigFactory.php +++ b/src/Config/Import/Source/Config/SourceConfigFactory.php @@ -24,9 +24,9 @@ public function createFromArray(array $config, string $basePath): SourceConfigIn $type = $config['type'] ?? 'local'; return match ($type) { - 'local' => LocalSourceConfig::fromArray($config, $basePath), - 'url' => UrlSourceConfig::fromArray($config, $basePath), - default => throw new \InvalidArgumentException("Unsupported source type: {$type}"), + 'local' => LocalSourceConfig::fromArray(config: $config, basePath: $basePath), + 'url' => UrlSourceConfig::fromArray(config: $config, basePath: $basePath), + default => throw new \InvalidArgumentException(message: "Unsupported source type: {$type}"), }; } } diff --git a/src/Config/Import/Source/ImportSourceProvider.php b/src/Config/Import/Source/ImportSourceProvider.php index b3835c33..2498243e 100644 --- a/src/Config/Import/Source/ImportSourceProvider.php +++ b/src/Config/Import/Source/ImportSourceProvider.php @@ -30,7 +30,7 @@ public function __construct( */ public function getSource(string $name): ImportSourceInterface { - return $this->getSourceRegistry()->get($name); + return $this->getSourceRegistry()->get(name: $name); } /** @@ -43,8 +43,8 @@ public function findSourceForConfig(SourceConfigInterface $config): ?ImportSourc { // First try to find source by type $sourceName = $config->getType(); - if ($this->getSourceRegistry()->has($sourceName)) { - $source = $this->getSourceRegistry()->get($sourceName); + if ($this->getSourceRegistry()->has(name: $sourceName)) { + $source = $this->getSourceRegistry()->get(name: $sourceName); if ($source->supports($config)) { return clone $source; } @@ -67,6 +67,6 @@ public function findSourceForConfig(SourceConfigInterface $config): ?ImportSourc private function getSourceRegistry(): ImportSourceRegistry { - return $this->container->get(ImportSourceRegistry::class); + return $this->container->get(id: ImportSourceRegistry::class); } } diff --git a/src/Config/Import/Source/ImportedConfig.php b/src/Config/Import/Source/ImportedConfig.php index b2a0cefe..df8ac24e 100644 --- a/src/Config/Import/Source/ImportedConfig.php +++ b/src/Config/Import/Source/ImportedConfig.php @@ -20,7 +20,7 @@ public function __construct( public function offsetExists(mixed $offset): bool { - return \array_key_exists($offset, $this->config); + return \array_key_exists(key: $offset, array: $this->config); } public function offsetGet(mixed $offset): mixed @@ -30,11 +30,11 @@ public function offsetGet(mixed $offset): mixed public function offsetSet(mixed $offset, mixed $value): void { - throw new \RuntimeException('Cannot set value in imported config'); + throw new \RuntimeException(message: 'Cannot set value in imported config'); } public function offsetUnset(mixed $offset): void { - throw new \RuntimeException('Cannot unset value in imported config'); + throw new \RuntimeException(message: 'Cannot unset value in imported config'); } } diff --git a/src/Config/Import/Source/Local/LocalImportSource.php b/src/Config/Import/Source/Local/LocalImportSource.php index e6aeb239..5ff9b1ca 100644 --- a/src/Config/Import/Source/Local/LocalImportSource.php +++ b/src/Config/Import/Source/Local/LocalImportSource.php @@ -34,9 +34,9 @@ public function __construct( parent::__construct($logger); // Initialize markdown-related dependencies - $markdownReader = new MarkdownMetadataReader($files, $logger); - $this->markdownDirectoryReader = new MarkdownDirectoryReader($markdownReader, $reporter, $logger); - $this->markdownTransformer = new MarkdownToResourceTransformer($logger); + $markdownReader = new MarkdownMetadataReader(files: $files, logger: $logger); + $this->markdownDirectoryReader = new MarkdownDirectoryReader(markdownReader: $markdownReader, reporter: $reporter, logger: $logger); + $this->markdownTransformer = new MarkdownToResourceTransformer(logger: $logger); } public function getName(): string @@ -53,7 +53,7 @@ public function supports(SourceConfigInterface $config): bool // For markdown imports, check if path is a directory if ($config->isMarkdownImport()) { - return \is_dir($config->getAbsolutePath()); + return \is_dir(filename: $config->getAbsolutePath()); } // For regular config imports, check if the file exists @@ -64,25 +64,25 @@ public function load(SourceConfigInterface $config): array { if (!$config instanceof LocalSourceConfig) { throw Exception\ImportSourceException::sourceNotSupported( - $config->getPath(), - $config->getType(), + path: $config->getPath(), + type: $config->getType(), ); } - if (!$this->supports($config)) { + if (!$this->supports(config: $config)) { throw Exception\ImportSourceException::sourceNotSupported( - $config->getPath(), - $config->getType(), + path: $config->getPath(), + type: $config->getType(), ); } // Handle markdown imports differently if ($config->isMarkdownImport()) { - return $this->loadMarkdownImport($config); + return $this->loadMarkdownImport(config: $config); } // Handle regular config file imports - return $this->loadConfigImport($config); + return $this->loadConfigImport(config: $config); } public function allowedSections(): array @@ -102,13 +102,13 @@ private function loadMarkdownImport(LocalSourceConfig $config): array ]); // Read all markdown files from the directory - $markdownData = $this->markdownDirectoryReader->read($config->getAbsolutePath()); + $markdownData = $this->markdownDirectoryReader->read(path: $config->getAbsolutePath()); // Transform markdown files into CTX resources - $transformedConfig = $this->markdownTransformer->transform($markdownData); + $transformedConfig = $this->markdownTransformer->transform(markdownData: $markdownData); // Process selective imports if specified - return $this->processSelectiveImports($transformedConfig, $config); + return $this->processSelectiveImports(config: $transformedConfig, sourceConfig: $config); } /** @@ -123,19 +123,19 @@ private function loadConfigImport(LocalSourceConfig $config): array ]); // Find an appropriate reader for the file - $reader = $this->getReaderForFile($config->getAbsolutePath()); + $reader = $this->getReaderForFile(path: $config->getAbsolutePath()); if (!$reader) { throw new Exception\ImportSourceException( - \sprintf('Unsupported file format for import: %s', $config->getAbsolutePath()), + message: \sprintf('Unsupported file format for import: %s', $config->getAbsolutePath()), ); } // Read and parse the configuration - $importedConfig = $this->readConfig($config->getAbsolutePath(), $reader); + $importedConfig = $this->readConfig(path: $config->getAbsolutePath(), reader: $reader); // Process selective imports if specified - return $this->processSelectiveImports($importedConfig, $config); + return $this->processSelectiveImports(config: $importedConfig, sourceConfig: $config); } /** @@ -143,10 +143,10 @@ private function loadConfigImport(LocalSourceConfig $config): array */ private function getReaderForFile(string $path): ?ReaderInterface { - $extension = \pathinfo($path, PATHINFO_EXTENSION); + $extension = \pathinfo(path: $path, flags: PATHINFO_EXTENSION); - if ($this->readers->has($extension)) { - return $this->readers->get($extension); + if ($this->readers->has(ext: $extension)) { + return $this->readers->get(ext: $extension); } return null; diff --git a/src/Config/Import/Source/Local/LocalSourceConfig.php b/src/Config/Import/Source/Local/LocalSourceConfig.php index 03ca6fa5..84a7717a 100644 --- a/src/Config/Import/Source/Local/LocalSourceConfig.php +++ b/src/Config/Import/Source/Local/LocalSourceConfig.php @@ -38,18 +38,18 @@ public function __construct( public static function fromArray(array $config, string $basePath): self { if (!isset($config['path'])) { - throw new \InvalidArgumentException("Source configuration must have a 'path' property"); + throw new \InvalidArgumentException(message: "Source configuration must have a 'path' property"); } $path = $config['path']; $pathPrefix = $config['pathPrefix'] ?? null; $selectiveDocuments = $config['docs'] ?? null; - $filter = FilterConfig::fromArray($config['filter'] ?? null); + $filter = FilterConfig::fromArray(config: $config['filter'] ?? null); $format = $config['format'] ?? 'config'; // Validate format - if (!\in_array($format, ['config', 'md', 'markdown'], true)) { - throw new \InvalidArgumentException("Unsupported format: {$format}. Supported formats: config, md, markdown"); + if (!\in_array(needle: $format, haystack: ['config', 'md', 'markdown'], strict: true)) { + throw new \InvalidArgumentException(message: "Unsupported format: {$format}. Supported formats: config, md, markdown"); } // Normalize markdown format @@ -58,10 +58,10 @@ public static function fromArray(array $config, string $basePath): self } // Check if the path contains wildcards - $hasWildcard = PathMatcher::containsWildcard($path); + $hasWildcard = PathMatcher::containsWildcard(path: $path); // Resolve relative path to absolute path - $absolutePath = (string) FSPath::create($basePath)->join($path); + $absolutePath = (string) FSPath::create(path: $basePath)->join($path); return new self( path: $path, @@ -114,7 +114,7 @@ public function hasWildcard(): bool #[\Override] public function getConfigDirectory(): string { - return \dirname($this->absolutePath); + return \dirname(path: $this->absolutePath); } public function jsonSerialize(): array diff --git a/src/Config/Import/Source/Local/MarkdownToResourceTransformer.php b/src/Config/Import/Source/Local/MarkdownToResourceTransformer.php index bebc98bd..4655051e 100644 --- a/src/Config/Import/Source/Local/MarkdownToResourceTransformer.php +++ b/src/Config/Import/Source/Local/MarkdownToResourceTransformer.php @@ -20,7 +20,7 @@ public function __construct( */ public function transform(array $markdownData): array { - if (!isset($markdownData['markdownFiles']) || !\is_array($markdownData['markdownFiles'])) { + if (!isset($markdownData['markdownFiles']) || !\is_array(value: $markdownData['markdownFiles'])) { $this->logger?->warning('Invalid markdown data structure'); return []; } @@ -32,7 +32,7 @@ public function transform(array $markdownData): array ]; foreach ($markdownData['markdownFiles'] as $fileData) { - $resource = $this->transformSingleFile($fileData); + $resource = $this->transformSingleFile(fileData: $fileData); if ($resource !== null) { $resourceType = $resource['_type']; unset($resource['_type']); @@ -42,12 +42,12 @@ public function transform(array $markdownData): array } // Remove empty sections - $config = \array_filter($config, static fn(array $section) => !empty($section)); + $config = \array_filter(array: $config, callback: static fn(array $section) => !empty($section)); $this->logger?->debug('Transformation completed', [ - 'documentsCount' => \count($config['documents'] ?? []), - 'promptsCount' => \count($config['prompts'] ?? []), - 'resourcesCount' => \count($config['resources'] ?? []), + 'documentsCount' => \count(value: $config['documents'] ?? []), + 'promptsCount' => \count(value: $config['prompts'] ?? []), + 'resourcesCount' => \count(value: $config['resources'] ?? []), ]); return $config; @@ -64,17 +64,17 @@ private function transformSingleFile(array $fileData): ?array $relativePath = $fileData['relativePath'] ?? ''; // Determine resource type from metadata or default to 'resource' - $resourceType = $this->determineResourceType($metadata); + $resourceType = $this->determineResourceType(metadata: $metadata); // Generate ID from filename if not provided in metadata - $id = $metadata['id'] ?? $this->generateIdFromFilename($name); + $id = $metadata['id'] ?? $this->generateIdFromFilename(filename: $name); // Get description with fallback hierarchy - $description = $this->getDescription($metadata, $relativePath); + $description = $this->getDescription(metadata: $metadata, relativePath: $relativePath); return match ($resourceType) { - 'prompt' => $this->createPromptResource($id, $metadata, $content, $relativePath, $description), - default => $this->createGenericResource($id, $metadata, $content, $relativePath, $description), + 'prompt' => $this->createPromptResource(id: $id, metadata: $metadata, content: $content, relativePath: $relativePath, description: $description), + default => $this->createGenericResource(id: $id, metadata: $metadata, content: $content, relativePath: $relativePath, description: $description), }; } @@ -102,8 +102,8 @@ private function determineResourceType(array $metadata): string { // Check explicit type declaration if (isset($metadata['type'])) { - $type = \strtolower($metadata['type']); - if (\in_array($type, ['prompt', 'resource'], true)) { + $type = \strtolower(string: $metadata['type']); + if (\in_array(needle: $type, haystack: ['prompt', 'resource'], strict: true)) { return $type; } } @@ -136,7 +136,7 @@ private function createPromptResource(string $id, array $metadata, string $conte // Add tags if present if (!empty($metadata['tags'])) { - $prompt['tags'] = $this->normalizeTagsArray($metadata['tags']); + $prompt['tags'] = $this->normalizeTagsArray(tags: $metadata['tags']); } // Add schema if present @@ -157,7 +157,7 @@ private function createPromptResource(string $id, array $metadata, string $conte 'description' => $description, 'type' => $prompt['type'], 'hasSchema' => isset($prompt['schema']), - 'messagesCount' => \count($prompt['messages']), + 'messagesCount' => \count(value: $prompt['messages']), 'hasTitle' => !empty($metadata['title']), ]); @@ -182,11 +182,11 @@ private function createDocumentResource(string $id, array $metadata, string $con // Add tags if present if (!empty($metadata['tags'])) { - $document['tags'] = $this->normalizeTagsArray($metadata['tags']); + $document['tags'] = $this->normalizeTagsArray(tags: $metadata['tags']); } // Create sources - either from metadata or convert content to text source - if (!empty($metadata['sources']) && \is_array($metadata['sources'])) { + if (!empty($metadata['sources']) && \is_array(value: $metadata['sources'])) { $document['sources'] = $metadata['sources']; } else { // Convert content to a text source @@ -207,7 +207,7 @@ private function createDocumentResource(string $id, array $metadata, string $con $this->logger?->debug('Created document resource', [ 'description' => $description, 'outputPath' => $document['outputPath'], - 'sourcesCount' => \count($document['sources']), + 'sourcesCount' => \count(value: $document['sources']), 'hasTitle' => !empty($metadata['title']), ]); @@ -221,7 +221,7 @@ private function createGenericResource(string $id, array $metadata, string $cont { // For now, convert generic resources to documents // This provides a sensible default behavior - return $this->createDocumentResource($id, $metadata, $content, $relativePath, $description); + return $this->createDocumentResource(id: $id, metadata: $metadata, content: $content, relativePath: $relativePath, description: $description); } /** @@ -230,9 +230,9 @@ private function createGenericResource(string $id, array $metadata, string $cont private function generateIdFromFilename(string $filename): string { // Convert filename to a valid identifier - $id = \strtolower($filename); - $id = \preg_replace('/[^a-z0-9]+/', '-', $id); - $id = \trim((string) $id, '-'); + $id = \strtolower(string: $filename); + $id = \preg_replace(pattern: '/[^a-z0-9]+/', replacement: '-', subject: $id); + $id = \trim(string: (string) $id, characters: '-'); return $id ?: 'unknown'; } @@ -242,14 +242,14 @@ private function generateIdFromFilename(string $filename): string */ private function normalizeTagsArray(mixed $tags): array { - if (\is_string($tags)) { + if (\is_string(value: $tags)) { // Handle comma-separated string - return \array_map(\trim(...), \explode(',', $tags)); + return \array_map(callback: \trim(...), array: \explode(separator: ',', string: $tags)); } - if (\is_array($tags)) { + if (\is_array(value: $tags)) { // Filter to ensure all elements are strings - return \array_filter(\array_map(\strval(...), $tags)); + return \array_filter(array: \array_map(callback: \strval(...), array: $tags)); } return []; diff --git a/src/Config/Import/Source/Registry/ImportSourceRegistry.php b/src/Config/Import/Source/Registry/ImportSourceRegistry.php index 9aa4bc22..d26c4986 100644 --- a/src/Config/Import/Source/Registry/ImportSourceRegistry.php +++ b/src/Config/Import/Source/Registry/ImportSourceRegistry.php @@ -50,8 +50,8 @@ public function has(string $name): bool */ public function get(string $name): ImportSourceInterface { - if (!$this->has($name)) { - throw new \InvalidArgumentException("Import source not found: {$name}"); + if (!$this->has(name: $name)) { + throw new \InvalidArgumentException(message: "Import source not found: {$name}"); } return $this->sources[$name]; diff --git a/src/Config/Import/Source/Url/UrlImportSource.php b/src/Config/Import/Source/Url/UrlImportSource.php index 1cc9f4f7..b510a1bc 100644 --- a/src/Config/Import/Source/Url/UrlImportSource.php +++ b/src/Config/Import/Source/Url/UrlImportSource.php @@ -45,8 +45,8 @@ public function load(SourceConfigInterface $config): array { if (!$config instanceof UrlSourceConfig) { throw Exception\ImportSourceException::sourceNotSupported( - $config->getPath(), - $config->getType(), + path: $config->getPath(), + type: $config->getType(), ); } @@ -61,12 +61,12 @@ public function load(SourceConfigInterface $config): array } try { - $url = $this->container->get(VariableResolver::class)->resolve($config->url); - $headers = $this->container->get(VariableResolver::class)->resolve($config->headers); + $url = $this->container->get(id: VariableResolver::class)->resolve($config->url); + $headers = $this->container->get(id: VariableResolver::class)->resolve($config->headers); $this->logger->debug('Loading URL import', [ 'url' => $url, - 'headers' => \array_keys($headers), + 'headers' => \array_keys(array: $headers), ]); // Fetch the content from the URL @@ -75,21 +75,21 @@ public function load(SourceConfigInterface $config): array if (!$response->isSuccess()) { throw new Exception\ImportSourceException( - \sprintf('Failed to fetch URL: %s (status code: %d)', $url, $response->getStatusCode()), + message: \sprintf('Failed to fetch URL: %s (status code: %d)', $url, $response->getStatusCode()), ); } $content = $response->getBody(); // Determine content type and parse accordingly - $contentType = $this->getContentType($response->getHeader('Content-Type') ?? ''); + $contentType = $this->getContentType(contentTypeHeader: $response->getHeader(name: 'Content-Type') ?? ''); $extension = $config->getExtension(); // Parse content based on content type or URL extension - $importedConfig = $this->parseContent($content, $contentType, $extension); + $importedConfig = $this->parseContent(content: $content, contentType: $contentType, extension: $extension); // Process selective imports if specified - return $this->processSelectiveImports($importedConfig, $config); + return $this->processSelectiveImports(config: $importedConfig, sourceConfig: $config); } catch (\Throwable $e) { $this->logger->error('URL import failed', [ 'url' => $config->url, @@ -97,8 +97,8 @@ public function load(SourceConfigInterface $config): array ]); throw Exception\ImportSourceException::networkError( - $config->url, - $e->getMessage(), + url: $config->url, + message: $e->getMessage(), ); } } @@ -114,8 +114,8 @@ public function allowedSections(): array private function getContentType(string $contentTypeHeader): string { // Extract main content type, e.g. 'application/json; charset=utf-8' -> 'application/json' - if (\preg_match('/^([^;]+)/', $contentTypeHeader, $matches)) { - return \strtolower(\trim($matches[1])); + if (\preg_match(pattern: '/^([^;]+)/', subject: $contentTypeHeader, matches: $matches)) { + return \strtolower(string: \trim(string: $matches[1])); } return ''; @@ -128,18 +128,18 @@ private function parseContent(string $content, string $contentType, string $exte { // Try to determine format from content type if ($contentType === 'application/json') { - return (new StringJsonReader($content))->read(''); + return (new StringJsonReader(jsonContent: $content))->read(path: ''); } if ($contentType === 'application/yaml' || $contentType === 'application/x-yaml') { - return Yaml::parse($content); + return Yaml::parse(input: $content); } // If content type not determined, try by extension return match ($extension) { - 'json' => (new StringJsonReader($content))->read(''), - 'yaml', 'yml' => Yaml::parse($content), - default => throw new Exception\ImportSourceException('Unsupported content type for URL import'), + 'json' => (new StringJsonReader(jsonContent: $content))->read(path: ''), + 'yaml', 'yml' => Yaml::parse(input: $content), + default => throw new Exception\ImportSourceException(message: 'Unsupported content type for URL import'), }; } } diff --git a/src/Config/Import/Source/Url/UrlSourceConfig.php b/src/Config/Import/Source/Url/UrlSourceConfig.php index f09c93a3..27d5fc8b 100644 --- a/src/Config/Import/Source/Url/UrlSourceConfig.php +++ b/src/Config/Import/Source/Url/UrlSourceConfig.php @@ -31,15 +31,15 @@ public function __construct( public static function fromArray(array $config, string $basePath): self { if (!isset($config['url'])) { - throw new \InvalidArgumentException("Source configuration must have a 'url' property"); + throw new \InvalidArgumentException(message: "Source configuration must have a 'url' property"); } $url = $config['url']; $headers = $config['headers'] ?? []; - $filter = FilterConfig::fromArray($config['filter'] ?? null); + $filter = FilterConfig::fromArray(config: $config['filter'] ?? null); // Ensure headers is an array - if (!\is_array($headers)) { + if (!\is_array(value: $headers)) { $headers = []; } @@ -61,12 +61,12 @@ public function getType(): string */ public function getExtension(): string { - $parsedUrl = \parse_url($this->url); + $parsedUrl = \parse_url(url: $this->url); if (!isset($parsedUrl['path'])) { return ''; } - return \strtolower(\pathinfo($parsedUrl['path'], PATHINFO_EXTENSION)); + return \strtolower(string: \pathinfo(path: $parsedUrl['path'], flags: PATHINFO_EXTENSION)); } public function getPath(): string diff --git a/src/Config/Import/WildcardPathFinder.php b/src/Config/Import/WildcardPathFinder.php index 7ba92fad..c0a1c0f5 100644 --- a/src/Config/Import/WildcardPathFinder.php +++ b/src/Config/Import/WildcardPathFinder.php @@ -40,37 +40,37 @@ public function findMatchingPaths(string $pattern, string $basePath): array ]); // If the pattern doesn't contain wildcards, just check if the file exists - if (!PathMatcher::containsWildcard($pattern)) { - $path = $this->resolvePath($pattern, $basePath); + if (!PathMatcher::containsWildcard(path: $pattern)) { + $path = $this->resolvePath(path: $pattern, basePath: $basePath); return $this->files->exists($path) ? [$path] : []; } // Determine the base directory to start scanning from - $baseDir = $this->getBaseDirectoryFromPattern($pattern, $basePath); + $baseDir = $this->getBaseDirectoryFromPattern(pattern: $pattern, basePath: $basePath); // If base directory doesn't exist, no files can match - if (!\is_dir($baseDir)) { + if (!\is_dir(filename: $baseDir)) { $this->logger?->debug('Base directory does not exist', ['baseDir' => $baseDir]); return []; } // Extract the pattern part after the base directory - $patternSuffix = $this->getPatternSuffix($pattern, $baseDir, $basePath); + $patternSuffix = $this->getPatternSuffix(pattern: $pattern, baseDir: $baseDir, basePath: $basePath); try { // Create and configure Symfony Finder $finder = new Finder(); $finder ->files() - ->in($baseDir) - ->name('/\.(' . \implode('|', self::CONFIG_EXTENSIONS) . ')$/') + ->in(dirs: $baseDir) + ->name(patterns: '/\.(' . \implode(separator: '|', array: self::CONFIG_EXTENSIONS) . ')$/') ->followLinks(); // Apply the pattern as a path filter, but only if it's not just '*' if ($patternSuffix !== '*') { // Convert our glob pattern to a regex pattern compatible with Symfony's path() method - $regexPattern = $this->convertGlobToFinderPathRegex($patternSuffix); - $finder->path($regexPattern); + $regexPattern = $this->convertGlobToFinderPathRegex(pattern: $patternSuffix); + $finder->path(patterns: $regexPattern); } $matches = []; @@ -78,7 +78,7 @@ public function findMatchingPaths(string $pattern, string $basePath): array $matches[] = $file->getRealPath(); } - $this->logger?->debug('Found matching paths', ['count' => \count($matches), 'paths' => $matches]); + $this->logger?->debug('Found matching paths', ['count' => \count(value: $matches), 'paths' => $matches]); return $matches; } catch (\InvalidArgumentException $e) { // Finder throws this if the directory doesn't exist @@ -97,11 +97,11 @@ public function findMatchingPaths(string $pattern, string $basePath): array private function convertGlobToFinderPathRegex(string $pattern): string { // First, convert the glob pattern to a regex pattern using our PathMatcher - $matcher = new PathMatcher($pattern); + $matcher = new PathMatcher(pattern: $pattern); $regex = $matcher->getRegex(); // Extract the pattern part between the delimiters (remove the ~^ at the start and $ at the end) - $patternBody = \substr($regex, 2, -2); + $patternBody = \substr(string: $regex, offset: 2, length: -2); // Create a new regex pattern that will be recognized by Symfony Finder's path() method // We need to make sure it starts with a delimiter so it's recognized as a regex @@ -113,12 +113,12 @@ private function convertGlobToFinderPathRegex(string $pattern): string */ private function getPatternSuffix(string $pattern, string $baseDir, string $basePath): string { - $resolvedPattern = $this->resolvePath($pattern, $basePath); + $resolvedPattern = $this->resolvePath(path: $pattern, basePath: $basePath); // If baseDir is part of the resolved pattern, extract the suffix - $baseLength = \strlen($baseDir); - if (\strncmp($resolvedPattern, $baseDir, $baseLength) === 0) { - $suffix = \substr($resolvedPattern, $baseLength + 1); + $baseLength = \strlen(string: $baseDir); + if (\strncmp(string1: $resolvedPattern, string2: $baseDir, length: $baseLength) === 0) { + $suffix = \substr(string: $resolvedPattern, offset: $baseLength + 1); return $suffix ?: '*'; } @@ -131,15 +131,15 @@ private function getPatternSuffix(string $pattern, string $baseDir, string $base private function getBaseDirectoryFromPattern(string $pattern, string $basePath): string { // Find the position of the first wildcard - $firstWildcard = \strcspn($pattern, '*?[{'); + $firstWildcard = \strcspn(string: $pattern, characters: '*?[{'); // Get the part of the pattern before the first wildcard - $fixedPrefix = \substr($pattern, 0, $firstWildcard); + $fixedPrefix = \substr(string: $pattern, offset: 0, length: $firstWildcard); // Get the directory part of the fixed prefix $baseDir = $fixedPrefix; - if (\str_contains($fixedPrefix, '/')) { - $baseDir = \dirname($fixedPrefix); + if (\str_contains(haystack: $fixedPrefix, needle: '/')) { + $baseDir = \dirname(path: $fixedPrefix); } // If the base directory is empty, use the base path @@ -148,7 +148,7 @@ private function getBaseDirectoryFromPattern(string $pattern, string $basePath): } // Resolve the base directory against the base path - return $this->resolvePath($baseDir, $basePath); + return $this->resolvePath(path: $baseDir, basePath: $basePath); } /** @@ -157,11 +157,11 @@ private function getBaseDirectoryFromPattern(string $pattern, string $basePath): private function resolvePath(string $path, string $basePath): string { // If it's an absolute path, use it directly - if (\str_starts_with($path, '/')) { + if (\str_starts_with(haystack: $path, needle: '/')) { return $path; } // Otherwise, resolve it relative to the base path - return \rtrim($basePath, '/') . '/' . $path; + return \rtrim(string: $basePath, characters: '/') . '/' . $path; } } diff --git a/src/Config/ImportBootloader.php b/src/Config/ImportBootloader.php index f497d799..836d6889 100644 --- a/src/Config/ImportBootloader.php +++ b/src/Config/ImportBootloader.php @@ -38,8 +38,8 @@ public function defineSingletons(): array logger: $logger->withPrefix('import-source-registry'), ); - $registry->register($localImportSource); - $registry->register($urlImportSource); + $registry->register(source: $localImportSource); + $registry->register(source: $urlImportSource); return $registry; }, @@ -54,6 +54,6 @@ public function boot( ConfigLoaderBootloader $parserRegistry, ImportParserPlugin $importParserPlugin, ): void { - $parserRegistry->registerParserPlugin($importParserPlugin); + $parserRegistry->registerParserPlugin(plugin: $importParserPlugin); } } diff --git a/src/Config/Loader/CompositeConfigLoader.php b/src/Config/Loader/CompositeConfigLoader.php index 5657920d..47c74adb 100644 --- a/src/Config/Loader/CompositeConfigLoader.php +++ b/src/Config/Loader/CompositeConfigLoader.php @@ -21,7 +21,7 @@ public function __construct( public function load(): ConfigRegistry { $this->logger?->debug('Trying to load with composite loader', [ - 'loaderCount' => \count($this->loaders), + 'loaderCount' => \count(value: $this->loaders), ]); $compositeRegistry = new ConfigRegistry(); @@ -36,8 +36,8 @@ public function load(): ConfigRegistry // Merge all registry types from this loader foreach ($registry->all() as $type => $typeRegistry) { - if (!$compositeRegistry->has($type)) { - $compositeRegistry->register($typeRegistry); + if (!$compositeRegistry->has(type: $type)) { + $compositeRegistry->register(registry: $typeRegistry); $this->logger?->debug('Registered registry type', [ 'type' => $type, ]); @@ -50,7 +50,7 @@ public function load(): ConfigRegistry $this->logger?->debug('Successfully loaded with a loader', [ 'loaderClass' => $loader::class, - 'registryTypes' => \array_keys($registry->all()), + 'registryTypes' => \array_keys(array: $registry->all()), ]); } catch (\Throwable $e) { $this->logger?->warning('Failed to load with a loader', [ @@ -67,7 +67,7 @@ public function load(): ConfigRegistry public function loadRawConfig(): array { $this->logger?->debug('Trying to load raw config with composite loader', [ - 'loaderCount' => \count($this->loaders), + 'loaderCount' => \count(value: $this->loaders), ]); foreach ($this->loaders as $loader) { diff --git a/src/Config/Loader/ConfigLoader.php b/src/Config/Loader/ConfigLoader.php index a44324a7..869f0f9a 100644 --- a/src/Config/Loader/ConfigLoader.php +++ b/src/Config/Loader/ConfigLoader.php @@ -38,7 +38,7 @@ public function load(): ConfigRegistry $configRegistry = $this->parser->parse($config); // Log the available registry types - $registryTypes = \array_keys($configRegistry->all()); + $registryTypes = \array_keys(array: $configRegistry->all()); $this->logger?->info('Configuration loaded successfully', [ 'registryTypes' => $registryTypes, ]); diff --git a/src/Config/Loader/ConfigLoaderFactory.php b/src/Config/Loader/ConfigLoaderFactory.php index 77e0c185..b721f4b5 100644 --- a/src/Config/Loader/ConfigLoaderFactory.php +++ b/src/Config/Loader/ConfigLoaderFactory.php @@ -35,37 +35,37 @@ public function create(string $configPath): ConfigLoaderInterface // Create composite parser using the injected plugin registry $compositeParser = new CompositeConfigParser( new ConfigParser( - (string) $configPathObj, - $this->pluginRegistry, - $this->logger, + rootPath: (string) $configPathObj, + pluginRegistry: $this->pluginRegistry, + logger: $this->logger, ), ); // Try different file extensions $jsonLoader = new ConfigLoader( configPath: (string) $configPathObj->join('context.json'), - reader: $this->readers->get('json'), + reader: $this->readers->get(ext: 'json'), parser: $compositeParser, logger: $this->logger, ); $yamlLoader = new ConfigLoader( configPath: (string) $configPathObj->join('context.yaml'), - reader: $this->readers->get('yaml'), + reader: $this->readers->get(ext: 'yaml'), parser: $compositeParser, logger: $this->logger, ); $ymlLoader = new ConfigLoader( configPath: (string) $configPathObj->join('context.yml'), - reader: $this->readers->get('yml'), + reader: $this->readers->get(ext: 'yml'), parser: $compositeParser, logger: $this->logger, ); $phpLoader = new ConfigLoader( configPath: (string) $configPathObj->join('context.php'), - reader: $this->readers->get('php'), + reader: $this->readers->get(ext: 'php'), parser: $compositeParser, logger: $this->logger, ); @@ -93,12 +93,12 @@ public function createForFile(string $configPath): ConfigLoaderInterface $compositeParser = new CompositeConfigParser($parser); // Determine the file extension - $extension = \pathinfo((string) $configPathObj, PATHINFO_EXTENSION); + $extension = \pathinfo(path: (string) $configPathObj, flags: PATHINFO_EXTENSION); // Create loader for the specific file return new ConfigLoader( configPath: (string) $configPathObj, - reader: $this->readers->get($extension), + reader: $this->readers->get(ext: $extension), parser: $compositeParser, logger: $this->logger, ); diff --git a/src/Config/Parser/CompositeConfigParser.php b/src/Config/Parser/CompositeConfigParser.php index c5a991a0..692fb77a 100644 --- a/src/Config/Parser/CompositeConfigParser.php +++ b/src/Config/Parser/CompositeConfigParser.php @@ -32,8 +32,8 @@ public function parse(array $config): ConfigRegistry foreach ($parsedRegistry->all() as $type => $typeRegistry) { // Only register if not already registered - if (!$registry->has($type)) { - $registry->register($typeRegistry); + if (!$registry->has(type: $type)) { + $registry->register(registry: $typeRegistry); } } } diff --git a/src/Config/Parser/ConfigParser.php b/src/Config/Parser/ConfigParser.php index 2494d2f2..0a4e5484 100644 --- a/src/Config/Parser/ConfigParser.php +++ b/src/Config/Parser/ConfigParser.php @@ -23,7 +23,7 @@ public function parse(array $config): ConfigRegistry $registry = new ConfigRegistry(); // First, allow plugins to update the configuration (imports etc.) - $currentConfig = $this->preprocessConfig($config); + $currentConfig = $this->preprocessConfig(config: $config); foreach ($this->pluginRegistry->getPlugins() as $plugin) { try { @@ -34,7 +34,7 @@ public function parse(array $config): ConfigRegistry $parsedRegistry = $plugin->parse($currentConfig, $this->rootPath); if ($parsedRegistry !== null) { - $registry->register($parsedRegistry); + $registry->register(registry: $parsedRegistry); } } catch (\Throwable $e) { // Log the error and continue with other plugins diff --git a/src/Config/Parser/VariablesParserPlugin.php b/src/Config/Parser/VariablesParserPlugin.php index 2be74ec6..8ae0d5c6 100644 --- a/src/Config/Parser/VariablesParserPlugin.php +++ b/src/Config/Parser/VariablesParserPlugin.php @@ -27,24 +27,24 @@ public function getConfigKey(): string public function supports(array $config): bool { - return isset($config['variables']) && \is_array($config['variables']); + return isset($config['variables']) && \is_array(value: $config['variables']); } public function parse(array $config, string $rootPath): ?RegistryInterface { - if (!$this->supports($config)) { + if (!$this->supports(config: $config)) { return null; } $variables = $config['variables']; $this->logger?->debug('Parsing variables from config', [ - 'count' => \count($variables), - 'keys' => \array_keys($variables), + 'count' => \count(value: $variables), + 'keys' => \array_keys(array: $variables), ]); // Update the variables in the provider - $this->variableProvider->setVariables($variables); + $this->variableProvider->setVariables(variables: $variables); return null; } diff --git a/src/Config/Reader/AbstractReader.php b/src/Config/Reader/AbstractReader.php index 6c0ce671..f1839355 100644 --- a/src/Config/Reader/AbstractReader.php +++ b/src/Config/Reader/AbstractReader.php @@ -31,16 +31,16 @@ public function read(string $path): array } catch (FilesException) { $errorMessage = \sprintf('Unable to read configuration file: %s', $path); $this->logger?->error($errorMessage); - throw new ReaderException($errorMessage); + throw new ReaderException(message: $errorMessage); } $this->logger?->debug('Parsing content', [ - 'contentLength' => \strlen($content), + 'contentLength' => \strlen(string: $content), 'reader' => static::class, ]); try { - $config = $this->parseContent($content); + $config = $this->parseContent(content: $content); $this->logger?->debug('Content successfully parsed', [ 'reader' => static::class, ]); @@ -62,8 +62,8 @@ public function supports(string $path): bool return false; } - $extension = \pathinfo($path, PATHINFO_EXTENSION); - $isSupported = \in_array($extension, $this->getSupportedExtensions(), true); + $extension = \pathinfo(path: $path, flags: PATHINFO_EXTENSION); + $isSupported = \in_array(needle: $extension, haystack: $this->getSupportedExtensions(), strict: true); $this->logger?->debug('Checking if config file is supported', [ 'path' => $path, diff --git a/src/Config/Reader/ConfigReaderRegistry.php b/src/Config/Reader/ConfigReaderRegistry.php index d7fb7cdd..7a0b753f 100644 --- a/src/Config/Reader/ConfigReaderRegistry.php +++ b/src/Config/Reader/ConfigReaderRegistry.php @@ -14,7 +14,7 @@ public function __construct( public function has(string $ext): bool { foreach ($this->readers as $reader) { - if (\in_array($ext, $reader->getSupportedExtensions(), true)) { + if (\in_array(needle: $ext, haystack: $reader->getSupportedExtensions(), strict: true)) { return true; } } @@ -25,11 +25,11 @@ public function has(string $ext): bool public function get(string $ext): ReaderInterface { foreach ($this->readers as $reader) { - if (\in_array($ext, $reader->getSupportedExtensions(), true)) { + if (\in_array(needle: $ext, haystack: $reader->getSupportedExtensions(), strict: true)) { return $reader; } } - throw new \RuntimeException(\sprintf('No reader found for extension: %s', $ext)); + throw new \RuntimeException(message: \sprintf('No reader found for extension: %s', $ext)); } } diff --git a/src/Config/Reader/JsonReader.php b/src/Config/Reader/JsonReader.php index c1afa086..fe5bafbc 100644 --- a/src/Config/Reader/JsonReader.php +++ b/src/Config/Reader/JsonReader.php @@ -23,8 +23,8 @@ protected function parseContent(string $content): array try { $config = \json_decode($content, true, flags: JSON_THROW_ON_ERROR); - if (!\is_array($config)) { - throw new ReaderException('JSON configuration must decode to an array'); + if (!\is_array(value: $config)) { + throw new ReaderException(message: 'JSON configuration must decode to an array'); } return $config; diff --git a/src/Config/Reader/MarkdownDirectoryReader.php b/src/Config/Reader/MarkdownDirectoryReader.php index c702d625..6dfe2b0f 100644 --- a/src/Config/Reader/MarkdownDirectoryReader.php +++ b/src/Config/Reader/MarkdownDirectoryReader.php @@ -27,17 +27,17 @@ public function read(string $path): array 'path' => $path, ]); - if (!\is_dir($path)) { - throw new ReaderException("Directory does not exist: {$path}"); + if (!\is_dir(filename: $path)) { + throw new ReaderException(message: "Directory does not exist: {$path}"); } try { $finder = new Finder(); $finder ->files() - ->in($path) - ->name('*.md') - ->name('*.markdown') + ->in(dirs: $path) + ->name(patterns: '*.md') + ->name(patterns: '*.markdown') ->followLinks() ->sortByName(); @@ -48,15 +48,15 @@ public function read(string $path): array try { // Read and parse the markdown file - $parsedContent = $this->markdownReader->read($filePath); + $parsedContent = $this->markdownReader->read(path: $filePath); // Add file information to the parsed content $markdownFiles[] = [ 'file' => $filePath, 'relativePath' => $file->getRelativePathname(), 'name' => match ($file->getExtension()) { - 'md' => $file->getBasename('.md'), - 'markdown' => $file->getBasename('.markdown'), + 'md' => $file->getBasename(suffix: '.md'), + 'markdown' => $file->getBasename(suffix: '.markdown'), default => $file->getBasename(), }, 'metadata' => $parsedContent['metadata'] ?? [], @@ -74,13 +74,13 @@ public function read(string $path): array $this->logger?->debug('Directory scan completed', [ 'path' => $path, - 'filesFound' => \count($markdownFiles), + 'filesFound' => \count(value: $markdownFiles), ]); return [ 'markdownFiles' => $markdownFiles, 'scannedPath' => $path, - 'totalFiles' => \count($markdownFiles), + 'totalFiles' => \count(value: $markdownFiles), ]; } catch (\Throwable $e) { @@ -95,7 +95,7 @@ public function read(string $path): array public function supports(string $path): bool { // This reader supports directories - return \is_dir($path); + return \is_dir(filename: $path); } public function getSupportedExtensions(): array diff --git a/src/Config/Reader/MarkdownMetadataReader.php b/src/Config/Reader/MarkdownMetadataReader.php index fd201765..fcc5c41a 100644 --- a/src/Config/Reader/MarkdownMetadataReader.php +++ b/src/Config/Reader/MarkdownMetadataReader.php @@ -32,8 +32,8 @@ public function supports(string $path): bool return false; } - $extension = \pathinfo($path, PATHINFO_EXTENSION); - $isSupported = \in_array($extension, $this->getSupportedExtensions(), true); + $extension = \pathinfo(path: $path, flags: PATHINFO_EXTENSION); + $isSupported = \in_array(needle: $extension, haystack: $this->getSupportedExtensions(), strict: true); $this->logger?->debug('Checking if markdown file is supported', [ 'path' => $path, @@ -57,22 +57,22 @@ public function read(string $path): array } catch (FilesException) { $errorMessage = \sprintf('Unable to read markdown file: %s', $path); $this->logger?->error($errorMessage); - throw new ReaderException($errorMessage); + throw new ReaderException(message: $errorMessage); } $this->logger?->debug('Parsing markdown content', [ 'path' => $path, - 'contentLength' => \strlen($content), + 'contentLength' => \strlen(string: $content), 'reader' => self::class, ]); try { - $result = $this->parseContent($content); + $result = $this->parseContent(content: $content); $this->logger?->debug('Markdown content successfully parsed', [ 'path' => $path, 'hasMetadata' => !empty($result['metadata']), - 'metadataKeys' => \array_keys($result['metadata'] ?? []), - 'contentLength' => \strlen($result['content'] ?? ''), + 'metadataKeys' => \array_keys(array: $result['metadata'] ?? []), + 'contentLength' => \strlen(string: $result['content'] ?? ''), 'reader' => self::class, ]); @@ -102,14 +102,14 @@ public function read(string $path): array private function parseContent(string $content): array { // Check if content starts with frontmatter delimiter - if (\str_starts_with(\trim($content), '---')) { - return $this->parseWithFrontmatter($content); + if (\str_starts_with(haystack: \trim(string: $content), needle: '---')) { + return $this->parseWithFrontmatter(content: $content); } // No frontmatter - check for title from first header $this->logger?->debug('No frontmatter found, checking for header title'); - return $this->parseWithoutFrontmatter($content); + return $this->parseWithoutFrontmatter(content: $content); } /** @@ -118,16 +118,16 @@ private function parseContent(string $content): array private function parseWithFrontmatter(string $content): array { // Split content by frontmatter delimiters - $parts = \preg_split('/^---\s*$/m', $content, 3); + $parts = \preg_split(pattern: '/^---\s*$/m', subject: $content, limit: 3); - if (\count($parts) < 3) { + if (\count(value: $parts) < 3) { $this->logger?->debug('Invalid frontmatter format, falling back to header extraction'); - return $this->parseWithoutFrontmatter($content); + return $this->parseWithoutFrontmatter(content: $content); } // Extract frontmatter (second part, first part is empty) - $frontmatter = \trim($parts[1]); - $markdownContent = \trim($parts[2]); + $frontmatter = \trim(string: $parts[1]); + $markdownContent = \trim(string: $parts[2]); $result = [ 'metadata' => [], @@ -137,9 +137,9 @@ private function parseWithFrontmatter(string $content): array // Parse YAML frontmatter try { if (!empty($frontmatter)) { - $metadata = Yaml::parse($frontmatter) ?: []; - if (!\is_array($metadata)) { - throw new \InvalidArgumentException('Frontmatter must be a YAML object'); + $metadata = Yaml::parse(input: $frontmatter) ?: []; + if (!\is_array(value: $metadata)) { + throw new \InvalidArgumentException(message: 'Frontmatter must be a YAML object'); } $result['metadata'] = $metadata; } @@ -152,7 +152,7 @@ private function parseWithFrontmatter(string $content): array // If no title in metadata, try to extract from first header in content if (empty($result['metadata']['title'])) { - $headerTitle = $this->extractTitleFromContent($markdownContent); + $headerTitle = $this->extractTitleFromContent(content: $markdownContent); if ($headerTitle !== null) { $result['metadata']['title'] = $headerTitle; $this->logger?->debug('Extracted title from content header', [ @@ -162,8 +162,8 @@ private function parseWithFrontmatter(string $content): array } $this->logger?->debug('Parsed markdown with frontmatter', [ - 'metadataKeys' => \array_keys($result['metadata']), - 'contentLength' => \strlen($markdownContent), + 'metadataKeys' => \array_keys(array: $result['metadata']), + 'contentLength' => \strlen(string: $markdownContent), 'hasTitle' => !empty($result['metadata']['title']), ]); @@ -181,7 +181,7 @@ private function parseWithoutFrontmatter(string $content): array ]; // Try to extract title from first header - $title = $this->extractTitleFromContent($content); + $title = $this->extractTitleFromContent(content: $content); if ($title !== null) { $result['metadata']['title'] = $title; $this->logger?->debug('Extracted title from header', [ @@ -190,7 +190,7 @@ private function parseWithoutFrontmatter(string $content): array } $this->logger?->debug('Parsed markdown without frontmatter', [ - 'contentLength' => \strlen($content), + 'contentLength' => \strlen(string: $content), 'hasTitle' => $title !== null, ]); @@ -207,10 +207,10 @@ private function extractTitleFromContent(string $content): ?string } // Split content into lines - $lines = \explode("\n", $content); + $lines = \explode(separator: "\n", string: $content); foreach ($lines as $line) { - $line = \trim($line); + $line = \trim(string: $line); // Skip empty lines if (empty($line)) { @@ -218,10 +218,10 @@ private function extractTitleFromContent(string $content): ?string } // Check if line starts with # (header) - if (\str_starts_with($line, '#')) { + if (\str_starts_with(haystack: $line, needle: '#')) { // Extract the title part after the # symbols - $title = \preg_replace('/^#+\s*/', '', $line); - $title = \trim((string) $title); + $title = \preg_replace(pattern: '/^#+\s*/', replacement: '', subject: $line); + $title = \trim(string: (string) $title); if (!empty($title)) { return $title; diff --git a/src/Config/Reader/PhpReader.php b/src/Config/Reader/PhpReader.php index f4064969..023230d2 100644 --- a/src/Config/Reader/PhpReader.php +++ b/src/Config/Reader/PhpReader.php @@ -21,8 +21,8 @@ public function read(string $path): array 'path' => $path, ]); - if (!$this->supports($path)) { - throw new ReaderException(\sprintf('Unsupported configuration file: %s', $path)); + if (!$this->supports(path: $path)) { + throw new ReaderException(message: \sprintf('Unsupported configuration file: %s', $path)); } // PHP files are special since they can return Registry objects directly @@ -34,14 +34,14 @@ public function read(string $path): array } // If it's an array, return it directly - if (\is_array($result)) { + if (\is_array(value: $result)) { return $result; } throw new ReaderException( - \sprintf( + message: \sprintf( 'PHP configuration file must return an array or a RegistryInterface instance, got %s', - \gettype($result), + \gettype(value: $result), ), ); } @@ -54,6 +54,6 @@ public function getSupportedExtensions(): array protected function parseContent(string $content): array { // Not used for PHP files since we use require directly - throw new \LogicException('PHP files are not parsed from content, this method should not be called'); + throw new \LogicException(message: 'PHP files are not parsed from content, this method should not be called'); } } diff --git a/src/Config/Reader/StringJsonReader.php b/src/Config/Reader/StringJsonReader.php index 368d8847..e0997234 100644 --- a/src/Config/Reader/StringJsonReader.php +++ b/src/Config/Reader/StringJsonReader.php @@ -17,14 +17,14 @@ public function __construct(private string $jsonContent, private ?LoggerInterfac public function read(string $path): array { $this->logger?->debug('Reading JSON configuration from string', [ - 'contentLength' => \strlen($this->jsonContent), + 'contentLength' => \strlen(string: $this->jsonContent), ]); try { $config = \json_decode($this->jsonContent, true, flags: JSON_THROW_ON_ERROR); - if (!\is_array($config)) { - throw new ReaderException('JSON configuration must decode to an array'); + if (!\is_array(value: $config)) { + throw new ReaderException(message: 'JSON configuration must decode to an array'); } $this->logger?->debug('JSON string successfully parsed'); diff --git a/src/Config/Reader/YamlReader.php b/src/Config/Reader/YamlReader.php index 6ba1fd70..f8a10a30 100644 --- a/src/Config/Reader/YamlReader.php +++ b/src/Config/Reader/YamlReader.php @@ -23,13 +23,13 @@ public function getSupportedExtensions(): array protected function parseContent(string $content): array { try { - if (!\class_exists(Yaml::class)) { + if (!\class_exists(class: Yaml::class)) { throw new ReaderException( - 'Symfony Yaml component is required to parse YAML files. Please install symfony/yaml package.', + message: 'Symfony Yaml component is required to parse YAML files. Please install symfony/yaml package.', ); } - return (array) Yaml::parse($content); + return (array) Yaml::parse(input: $content); } catch (ParseException $e) { throw new ReaderException('Invalid YAML in configuration file', previous: $e); } diff --git a/src/Config/Registry/ConfigRegistry.php b/src/Config/Registry/ConfigRegistry.php index e4493a02..7c0b6512 100644 --- a/src/Config/Registry/ConfigRegistry.php +++ b/src/Config/Registry/ConfigRegistry.php @@ -45,15 +45,15 @@ public function has(string $type): bool */ public function get(string $type, string $className): RegistryInterface { - if (!$this->has($type)) { - throw new \InvalidArgumentException(\sprintf('Registry of type "%s" does not exist', $type)); + if (!$this->has(type: $type)) { + throw new \InvalidArgumentException(message: \sprintf('Registry of type "%s" does not exist', $type)); } $registry = $this->registries[$type]; if (!$registry instanceof $className) { throw new \InvalidArgumentException( - \sprintf('Registry of type "%s" is not an instance of "%s"', $type, $className), + message: \sprintf('Registry of type "%s" is not an instance of "%s"', $type, $className), ); } @@ -81,8 +81,8 @@ public function jsonSerialize(): array } return \array_filter( - $data, - static fn($value) => $value !== null && $value !== [], + array: $data, + callback: static fn($value) => $value !== null && $value !== [], ); } } diff --git a/src/Config/Registry/ConfigRegistryAccessor.php b/src/Config/Registry/ConfigRegistryAccessor.php index f7e04d97..5e64df60 100644 --- a/src/Config/Registry/ConfigRegistryAccessor.php +++ b/src/Config/Registry/ConfigRegistryAccessor.php @@ -23,7 +23,7 @@ public function __construct( */ public function getDocuments(): ?DocumentRegistry { - return $this->getRegistry('documents', DocumentRegistry::class); + return $this->getRegistry(type: 'documents', className: DocumentRegistry::class); } /** @@ -31,7 +31,7 @@ public function getDocuments(): ?DocumentRegistry */ public function getPrompts(): ?PromptRegistry { - return $this->getRegistry('prompts', PromptRegistry::class); + return $this->getRegistry(type: 'prompts', className: PromptRegistry::class); } /** @@ -39,7 +39,7 @@ public function getPrompts(): ?PromptRegistry */ public function getTools(): ?ToolRegistry { - return $this->getRegistry('tools', ToolRegistry::class); + return $this->getRegistry(type: 'tools', className: ToolRegistry::class); } /** @@ -47,7 +47,7 @@ public function getTools(): ?ToolRegistry */ public function getImports(): ?ImportRegistry { - return $this->getRegistry('import', ImportRegistry::class); + return $this->getRegistry(type: 'import', className: ImportRegistry::class); } /** @@ -60,12 +60,12 @@ public function getImports(): ?ImportRegistry */ private function getRegistry(string $type, string $className): ?RegistryInterface { - if (!$this->registry->has($type)) { + if (!$this->registry->has(type: $type)) { return null; } try { - return $this->registry->get($type, $className); + return $this->registry->get(type: $type, className: $className); } catch (\InvalidArgumentException) { return null; } diff --git a/src/Console/BaseCommand.php b/src/Console/BaseCommand.php index f744cb05..4612f0cd 100644 --- a/src/Console/BaseCommand.php +++ b/src/Console/BaseCommand.php @@ -26,7 +26,7 @@ abstract class BaseCommand extends Command #[\Override] protected function execute(InputInterface $input, OutputInterface $output): int { - \assert($output instanceof SymfonyStyle); + \assert(assertion: $output instanceof SymfonyStyle); $this->input = $input; $this->output = $output; @@ -43,8 +43,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int $this->logger = $logger; - \assert($this->logger instanceof HasPrefixLoggerInterface); - \assert($this->logger instanceof LoggerInterface); + \assert(assertion: $this->logger instanceof HasPrefixLoggerInterface); + \assert(assertion: $this->logger instanceof LoggerInterface); $this->container ->get(BinderInterface::class) diff --git a/src/Console/GenerateCommand.php b/src/Console/GenerateCommand.php index 48ac09c0..58005719 100644 --- a/src/Console/GenerateCommand.php +++ b/src/Console/GenerateCommand.php @@ -67,7 +67,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int ->withOutputPath($this->workDir) ->withEnvFile($this->envFileName); - $container->getBinder('root')->bind( + $container->getBinder(scope: 'root')->bind( DirectoriesInterface::class, $dirs, ); @@ -95,10 +95,10 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int // Get the appropriate loader based on options provided if ($this->inlineJson !== null) { $this->logger->info('Using inline JSON configuration...'); - $loader = $configProvider->fromString($this->inlineJson); + $loader = $configProvider->fromString(jsonConfig: $this->inlineJson); } elseif ($this->configPath !== null) { $this->logger->info(\sprintf('Loading configuration from %s...', $this->configPath)); - $loader = $configProvider->fromPath($dirs->getConfigPath()->toString()); + $loader = $configProvider->fromPath(configPath: $dirs->getConfigPath()->toString()); } else { $this->logger->info('Loading configuration from default location...'); $loader = $configProvider->fromDefaultLocation(); @@ -109,7 +109,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int ]); if ($this->asJson) { - $this->output->writeln(\json_encode([ + $this->output->writeln(\json_encode(value: [ 'status' => 'error', 'message' => 'Failed to load configuration', 'error' => $e->getMessage(), @@ -131,16 +131,16 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int // Display summary header $this->output->writeln(''); - $config = new ConfigRegistryAccessor($loader->load()); + $config = new ConfigRegistryAccessor(registry: $loader->load()); $imports = $config->getImports(); if ($imports !== null && !$this->asJson) { - $renderer->renderImports($imports); + $renderer->renderImports(imports: $imports); } if ($config->getDocuments() === null || $config->getDocuments()->getItems() === []) { if ($this->asJson) { - $this->output->writeln(\json_encode([ + $this->output->writeln(\json_encode(value: [ 'status' => 'success', 'message' => 'No documents found in configuration.', 'imports' => $imports, @@ -159,10 +159,10 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int foreach ($config->getDocuments() as $document) { $this->logger->info(\sprintf('Compiling %s...', $document->description)); - $compiledDocument = $compiler->compile($document); + $compiledDocument = $compiler->compile(document: $document); if (!$this->asJson) { - $renderer->renderCompilationResult($document, $compiledDocument); + $renderer->renderCompilationResult(document: $document, compiledDocument: $compiledDocument); } else { $result[] = [ 'output_path' => $compiledDocument->outputPath, @@ -173,7 +173,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int } if ($this->asJson) { - $this->output->writeln(\json_encode([ + $this->output->writeln(\json_encode(value: [ 'status' => 'success', 'message' => 'Documents compiled successfully', 'result' => $result, diff --git a/src/Console/Renderer/GenerateCommandRenderer.php b/src/Console/Renderer/GenerateCommandRenderer.php index a943e48a..83066c8c 100644 --- a/src/Console/Renderer/GenerateCommandRenderer.php +++ b/src/Console/Renderer/GenerateCommandRenderer.php @@ -44,22 +44,22 @@ public function __construct( public function renderImports(ImportRegistry $imports): void { - \assert($this->output instanceof SymfonyStyle); + \assert(assertion: $this->output instanceof SymfonyStyle); foreach ($imports as $item) { $description = $item->getPath(); - if (\strlen($description) > self::MAX_LINE_WIDTH - 40) { + if (\strlen(string: $description) > self::MAX_LINE_WIDTH - 40) { $halfLength = (self::MAX_LINE_WIDTH - 40) / 2; - $description = \substr($description, 0, $halfLength) . '...' . \substr($description, -$halfLength); + $description = \substr(string: $description, offset: 0, length: $halfLength) . '...' . \substr(string: $description, offset: -$halfLength); } // Calculate padding to align the document descriptions - $padding = $this->calculatePadding($item->getType(), $description, 12); + $padding = $this->calculatePadding(description: $item->getType(), outputPath: $description, additional: 12); $this->output->writeln( - \sprintf( + messages: \sprintf( ' %s Import %s [%s]%s', - $this->padRight(self::SUCCESS_SYMBOL, 1), + $this->padRight(text: self::SUCCESS_SYMBOL, length: 1), $item->getType(), $description, $padding, @@ -75,21 +75,21 @@ public function renderImports(ImportRegistry $imports): void */ public function renderCompilationResult(Document $document, CompiledDocument $compiledDocument): void { - \assert($this->output instanceof SymfonyStyle); + \assert(assertion: $this->output instanceof SymfonyStyle); $hasErrors = $compiledDocument->errors->hasErrors(); $description = $document->description; $outputPath = $document->outputPath; // Calculate padding to align the document descriptions - $stats = $this->getFileStatistics($outputPath); - $padding = $this->calculatePadding($description, $outputPath); + $stats = $this->getFileStatistics(outputPath: $outputPath); + $padding = $this->calculatePadding(description: $description, outputPath: $outputPath); if ($hasErrors) { // Render warning line with document info $this->output->writeln( - \sprintf( + messages: \sprintf( ' %s %s [%s]%s', - $this->padRight(self::WARNING_SYMBOL, 1), + $this->padRight(text: self::WARNING_SYMBOL, length: 1), $description, $outputPath, $padding, @@ -98,13 +98,13 @@ public function renderCompilationResult(Document $document, CompiledDocument $co // Render errors foreach ($compiledDocument->errors as $error) { - $this->output->writeln(\sprintf(' %s %s', self::ERROR_SYMBOL, $error)); + $this->output->writeln(messages: \sprintf(' %s %s', self::ERROR_SYMBOL, $error)); } $this->output->newLine(); } else { // Render success line with document info and file statistics - $this->renderSuccessWithStats($description, $outputPath, $stats, $padding); + $this->renderSuccessWithStats(description: $description, outputPath: $outputPath, stats: $stats, padding: $padding); } } @@ -121,7 +121,7 @@ private function renderSuccessWithStats(string $description, string $outputPath, $this->output->writeln( \sprintf( ' %s %s [%s]%s%s', - $this->padRight(self::SUCCESS_SYMBOL, 2), + $this->padRight(text: self::SUCCESS_SYMBOL, length: 2), $description, $outputPath, $padding, @@ -141,7 +141,7 @@ private function getFileStatistics(string $outputPath): ?array try { $fullPath = $this->basePath . '/' . $outputPath; - $fullPath = \str_replace('//', '/', $fullPath); + $fullPath = \str_replace(search: '//', replace: '/', subject: $fullPath); if (!$this->files->exists($fullPath)) { return null; @@ -149,10 +149,10 @@ private function getFileStatistics(string $outputPath): ?array $fileSize = $this->files->size($fullPath); $fileContent = $this->files->read($fullPath); - $lineCount = \substr_count($fileContent, "\n") + 1; + $lineCount = \substr_count(haystack: $fileContent, needle: "\n") + 1; return [ - 'size' => $this->formatSize($fileSize), + 'size' => $this->formatSize(bytes: $fileSize), 'lines' => $lineCount, ]; } catch (\Throwable $e) { @@ -175,15 +175,15 @@ private function formatSize(int $bytes): string $units = ['B', 'KB', 'MB', 'GB']; $i = 0; - while ($bytes >= 1024 && $i < \count($units) - 1) { + while ($bytes >= 1024 && $i < \count(value: $units) - 1) { $bytes = (float) $bytes / 1024.0; $i++; } // Ensure $i is within bounds - $i = \min($i, \count($units) - 1); + $i = \min($i, \count(value: $units) - 1); - return (string) \round($bytes, 1) . ' ' . $units[$i]; + return (string) \round(num: $bytes, precision: 1) . ' ' . $units[$i]; } /** @@ -191,10 +191,10 @@ private function formatSize(int $bytes): string */ private function calculatePadding(string $description, string $outputPath, int $additional = 5): string { - $totalLength = \strlen($description) + \strlen($outputPath) + $additional; + $totalLength = \strlen(string: $description) + \strlen(string: $outputPath) + $additional; $padding = \max(0, self::MAX_LINE_WIDTH - $totalLength); - return \str_repeat('.', $padding); + return \str_repeat(string: '.', times: $padding); } /** @@ -202,6 +202,6 @@ private function calculatePadding(string $description, string $outputPath, int $ */ private function padRight(string $text, int $length): string { - return \str_pad($text, $length, ' ', \STR_PAD_RIGHT); + return \str_pad(string: $text, length: $length, pad_type: \STR_PAD_RIGHT); } } diff --git a/src/Console/Renderer/Style.php b/src/Console/Renderer/Style.php index ccb1738e..9dac2029 100644 --- a/src/Console/Renderer/Style.php +++ b/src/Console/Renderer/Style.php @@ -30,7 +30,7 @@ public static function section(string $text): string */ public static function separator(string $char = '-', int $length = 80): string { - return \sprintf('%s', \str_repeat($char, $length)); + return \sprintf('%s', \str_repeat(string: $char, times: $length)); } /** @@ -78,8 +78,8 @@ public static function itemNumber(int $current, int $total): string */ public static function indent(string $text, int $spaces = 2): string { - $indent = \str_repeat(' ', $spaces); - return $indent . \str_replace("\n", "\n" . $indent, $text); + $indent = \str_repeat(string: ' ', times: $spaces); + return $indent . \str_replace(search: "\n", replace: "\n" . $indent, subject: $text); } /** @@ -201,7 +201,7 @@ public static function keyValue(string $key, string $value, int $keyWidth = 15): { return \sprintf( '%s: %s', - self::property(\str_pad($key, $keyWidth)), + self::property(\str_pad(string: $key, length: $keyWidth)), self::value($value), ); } diff --git a/src/Console/SelfUpdateCommand.php b/src/Console/SelfUpdateCommand.php index 2c6c0542..5c7f713a 100644 --- a/src/Console/SelfUpdateCommand.php +++ b/src/Console/SelfUpdateCommand.php @@ -67,8 +67,8 @@ public function __construct( public function __invoke(Application $app, EnvironmentInterface $env, DirectoriesInterface $dirs): int { $this->output->title('CTX Self Update'); - $storeLocation = \trim($this->storeLocation ?: $env->get('CTX_BINARY_PATH', (string) $dirs->getBinaryPath())); - $type = \trim($this->type ?: ($app->isBinary ? 'bin' : 'phar')); + $storeLocation = \trim(string: $this->storeLocation ?: $env->get('CTX_BINARY_PATH', (string) $dirs->getBinaryPath())); + $type = \trim(string: $this->type ?: ($app->isBinary ? 'bin' : 'phar')); // Check if we have a valid store location if (empty($storeLocation)) { @@ -78,7 +78,7 @@ public function __invoke(Application $app, EnvironmentInterface $env, Directorie return Command::FAILURE; } - $binaryPath = (string) FSPath::create($storeLocation)->join($this->binaryName); + $binaryPath = (string) FSPath::create(path: $storeLocation)->join($this->binaryName); $this->output->title($app->name); $this->output->text('Current version: ' . $app->version); @@ -87,7 +87,7 @@ public function __invoke(Application $app, EnvironmentInterface $env, Directorie $this->output->section('Checking for updates...'); // Create repository and get standard release manager - $repository = new GithubRepository($this->repository); + $repository = new GithubRepository(repository: $this->repository); $baseReleaseManager = $this->githubClient->getReleaseManager($repository); try { @@ -95,7 +95,7 @@ public function __invoke(Application $app, EnvironmentInterface $env, Directorie $release = $baseReleaseManager->getLatestRelease(); // Check if an update is available - if (!$release->isNewerThan($app->version)) { + if (!$release->isNewerThan(currentVersion: $app->version)) { $this->output->success("You're already using the latest version ({$app->version})"); return Command::SUCCESS; } @@ -119,25 +119,24 @@ public function __invoke(Application $app, EnvironmentInterface $env, Directorie // Create an enhanced release manager with the binary name builder $releaseManager = new ReleaseManager( - $this->httpClient, - $repository, - null, // token - $binaryNameBuilder, - $this->logger, + httpClient: $this->httpClient, + repository: $repository, // token + binaryNameBuilder: $binaryNameBuilder, + logger: $this->logger, ); // Attempt to download the binary with platform awareness try { $this->output->text("Attempting to download platform-specific binary..."); $downloadSuccess = $releaseManager->downloadBinary( - $release->getVersion(), - $this->binaryName, - $type, - $tempFile, + version: $release->getVersion(), + binaryName: $this->binaryName, + type: $type, + destinationPath: $tempFile, ); if (!$downloadSuccess) { - throw new \RuntimeException("Failed to download binary"); + throw new \RuntimeException(message: "Failed to download binary"); } } catch (\Throwable $e) { $this->output->error("Failed to download platform-specific binary: {$e->getMessage()}"); @@ -147,10 +146,10 @@ public function __invoke(Application $app, EnvironmentInterface $env, Directorie $this->output->section('Installing the update...'); // Use our BinaryUpdater to handle the update safely - $updaterFactory = new UpdaterFactory($this->files, $this->logger); - $binaryUpdater = new BinaryUpdater($this->files, $updaterFactory->createStrategy(), $this->logger); + $updaterFactory = new UpdaterFactory(files: $this->files, logger: $this->logger); + $binaryUpdater = new BinaryUpdater(files: $this->files, strategy: $updaterFactory->createStrategy(), logger: $this->logger); - if ($binaryUpdater->update($tempFile, $binaryPath)) { + if ($binaryUpdater->update(sourcePath: $tempFile, targetPath: $binaryPath)) { $this->output->success("Update process started successfully for version {$release->getVersion()}"); // Add a note about how the update works diff --git a/src/Console/VersionCommand.php b/src/Console/VersionCommand.php index b00e598c..d6592b1f 100644 --- a/src/Console/VersionCommand.php +++ b/src/Console/VersionCommand.php @@ -46,7 +46,7 @@ public function __invoke(Application $app): int try { $latestVersion = $this->fetchLatestVersion(); - $isUpdateAvailable = $this->isUpdateAvailable($app->version, $latestVersion); + $isUpdateAvailable = $this->isUpdateAvailable(currentVersion: $app->version, latestVersion: $latestVersion); if ($isUpdateAvailable) { $this->output->success("A new version is available: {$latestVersion}"); @@ -91,18 +91,18 @@ private function fetchLatestVersion(): string if (!$response->isSuccess()) { throw new HttpException( - \sprintf('Failed to fetch latest version. Server returned status code %d', $response->getStatusCode()), + message: \sprintf('Failed to fetch latest version. Server returned status code %d', $response->getStatusCode()), ); } - $tagName = $response->getJsonValue('tag_name'); + $tagName = $response->getJsonValue(key: 'tag_name'); if ($tagName === null) { - throw new HttpException("Invalid response format: 'tag_name' missing"); + throw new HttpException(message: "Invalid response format: 'tag_name' missing"); } // Remove 'v' prefix if present - return \ltrim((string) $tagName, 'v'); + return \ltrim(string: (string) $tagName, characters: 'v'); } /** @@ -116,8 +116,8 @@ private function isUpdateAvailable(string $currentVersion, string $latestVersion } // Clean up versions for comparison - $currentVersion = \ltrim($currentVersion, 'v'); - $latestVersion = \ltrim($latestVersion, 'v'); + $currentVersion = \ltrim(string: $currentVersion, characters: 'v'); + $latestVersion = \ltrim(string: $latestVersion, characters: 'v'); return \version_compare($currentVersion, $latestVersion, '<'); } diff --git a/src/Directories.php b/src/Directories.php index a044dfaa..66a84acb 100644 --- a/src/Directories.php +++ b/src/Directories.php @@ -40,24 +40,24 @@ public function __construct( ) { // Ensure paths are not empty if ($rootPath === '') { - throw new \InvalidArgumentException('Root path cannot be empty'); + throw new \InvalidArgumentException(message: 'Root path cannot be empty'); } if ($outputPath === '') { - throw new \InvalidArgumentException('Output path cannot be empty'); + throw new \InvalidArgumentException(message: 'Output path cannot be empty'); } if ($configPath === '') { - throw new \InvalidArgumentException('Config path cannot be empty'); + throw new \InvalidArgumentException(message: 'Config path cannot be empty'); } if ($jsonSchemaPath === '') { - throw new \InvalidArgumentException('JSON schema path cannot be empty'); + throw new \InvalidArgumentException(message: 'JSON schema path cannot be empty'); } // Initialize FSPath objects - $this->binaryPathObj = FSPath::create($this->binaryPath ?? $this->resolveBinaryPath()); - $this->rootPathObj = FSPath::create($rootPath); - $this->outputPathObj = FSPath::create($outputPath); - $this->configPathObj = FSPath::create($configPath); - $this->envFilePathObj = $envFilePath !== null ? FSPath::create($envFilePath) : null; + $this->binaryPathObj = FSPath::create(path: $this->binaryPath ?? $this->resolveBinaryPath()); + $this->rootPathObj = FSPath::create(path: $rootPath); + $this->outputPathObj = FSPath::create(path: $outputPath); + $this->configPathObj = FSPath::create(path: $configPath); + $this->envFilePathObj = $envFilePath !== null ? FSPath::create(path: $envFilePath) : null; } public function getBinaryPath(): FSPath @@ -163,17 +163,17 @@ public function determineRootPath(?string $configPath = null, ?string $inlineCon } // If relative, resolve against the original root path - $configPathObj = FSPath::create($configPath); + $configPathObj = FSPath::create(path: $configPath); if ($configPathObj->isRelative()) { $configPath = $this->rootPathObj->join($configPath)->toString(); } // If config path is absolute, use its directory as root - $configDir = \rtrim(\is_dir($configPath) ? $configPath : \dirname($configPath), '/'); + $configDir = \rtrim(string: \is_dir(filename: $configPath) ? $configPath : \dirname(path: $configPath), characters: '/'); - if (\is_dir($configDir)) { - return $this->withRootPath($configDir)->withConfigPath($configPath); + if (\is_dir(filename: $configDir)) { + return $this->withRootPath(rootPath: $configDir)->withConfigPath(configPath: $configPath); } return $this; @@ -196,6 +196,6 @@ private function resolveBinaryPath(): string return $_SERVER['SCRIPT_NAME']; } - throw new \RuntimeException('Unable to determine binary path'); + throw new \RuntimeException(message: 'Unable to determine binary path'); } } diff --git a/src/Document/Compiler/DocumentCompiler.php b/src/Document/Compiler/DocumentCompiler.php index 35515459..52b99417 100644 --- a/src/Document/Compiler/DocumentCompiler.php +++ b/src/Document/Compiler/DocumentCompiler.php @@ -44,14 +44,14 @@ public function __construct( */ public function compile(Document $document): CompiledDocument { - $outputPath = $this->variables->resolve($document->outputPath); + $outputPath = $this->variables->resolve(strings: $document->outputPath); $this->logger?->info('Starting document compilation', [ 'outputPath' => $outputPath, ]); - $errors = new ErrorCollection($document->getErrors()); - $resultPath = (string) FSPath::create($this->basePath)->join($outputPath); + $errors = new ErrorCollection(errors: $document->getErrors()); + $resultPath = (string) FSPath::create(path: $this->basePath)->join($outputPath); if (!$document->overwrite && $this->files->exists($resultPath)) { $this->logger?->notice('Document already exists and overwrite is disabled', [ @@ -65,30 +65,30 @@ public function compile(Document $document): CompiledDocument } $this->logger?->debug('Building document content'); - $compiledDocument = $this->buildContent($errors, $document); + $compiledDocument = $this->buildContent(errors: $errors, document: $document); - $directory = \dirname($resultPath); + $directory = \dirname(path: $resultPath); $this->logger?->debug('Ensuring directory exists', ['directory' => $directory]); $this->files->ensureDirectory($directory); // Add file statistics to the generated content before writing - $finalContent = $this->addFileStatistics($compiledDocument->content, $resultPath, $outputPath); + $finalContent = $this->addFileStatistics(content: $compiledDocument->content, resultPath: $resultPath, outputPath: $outputPath); $this->logger?->debug('Writing compiled document to file', ['path' => $resultPath]); $this->files->write($resultPath, $finalContent); - $errorCount = \count($errors); + $errorCount = \count(value: $errors); if ($errorCount > 0) { $this->logger?->warning('Document compiled with errors', ['errorCount' => $errorCount]); } else { $this->logger?->info('Document compiled successfully', [ 'path' => $resultPath, - 'contentLength' => \strlen($finalContent), + 'contentLength' => \strlen(string: $finalContent), 'fileSize' => $this->files->size($resultPath), ]); } - return $compiledDocument->withOutputPath($this->basePath, $outputPath); + return $compiledDocument->withOutputPath(outputPath: $this->basePath, contextPath: $outputPath); } /** @@ -96,31 +96,31 @@ public function compile(Document $document): CompiledDocument */ public function buildContent(ErrorCollection $errors, Document $document): CompiledDocument { - $description = $this->variables->resolve($document->description); + $description = $this->variables->resolve(strings: $document->description); $this->logger?->debug('Creating content builder'); $builder = $this->builderFactory->create(); $this->logger?->debug('Adding document title', ['title' => $description]); - $builder->addTitle($description); + $builder->addTitle(title: $description); // Add document tags if present if ($document->hasTags()) { - $tags = \implode(', ', $document->getTags()); + $tags = \implode(separator: ', ', array: $document->getTags()); $this->logger?->debug('Adding document tags', ['tags' => $tags]); - $builder->addBlock(new TextBlock($tags, 'DOCUMENT_TAGS')); + $builder->addBlock(block: new TextBlock(content: $tags, tag: 'DOCUMENT_TAGS')); } $sources = $document->getSources(); - $sourceCount = \count($sources); + $sourceCount = \count(value: $sources); $this->logger?->info('Processing document sources', [ 'sourceCount' => $sourceCount, 'hasDocumentModifiers' => $document->hasModifiers(), ]); // Create a modifiers applier with document-level modifiers if present - $modifiersApplier = ModifiersApplier::empty($this->modifierRegistry, $this->logger) - ->withModifiers($document->getModifiers()); + $modifiersApplier = ModifiersApplier::empty(registry: $this->modifierRegistry, logger: $this->logger) + ->withModifiers(modifiers: $document->getModifiers()); // Process all sources foreach ($sources as $index => $source) { @@ -135,16 +135,16 @@ public function buildContent(ErrorCollection $errors, Document $document): Compi if ($source->hasDescription()) { $description = $source->getDescription(); $this->logger?->debug('Adding source description', ['description' => $description]); - $builder->addDescription("SOURCE: {$description}"); + $builder->addDescription(description: "SOURCE: {$description}"); } $this->logger?->debug('Parsing source content'); $content = $source->parseContent($this->parser, $modifiersApplier); $this->logger?->debug('Adding parsed content to builder', [ - 'contentLength' => \strlen($content), + 'contentLength' => \strlen(string: $content), ]); - $builder->addText($content); + $builder->addText(text: $content); $this->logger?->debug('Source processed successfully'); } catch (\Throwable $e) { @@ -156,7 +156,7 @@ public function buildContent(ErrorCollection $errors, Document $document): Compi ]); $errors->add( - new SourceError( + error: new SourceError( source: $source, exception: $e, ), @@ -191,11 +191,11 @@ private function addFileStatistics(string|\Stringable $content, string $resultPa $fileSize = $this->files->size($resultPath); $fileContent = $this->files->read($resultPath); - $lineCount = \substr_count($fileContent, "\n") + 1; // Count lines including the last line + $lineCount = \substr_count(haystack: $fileContent, needle: "\n") + 1; // Count lines including the last line // Create a new content builder with the original content $builder = $this->builderFactory->create(); - $builder->addText((string) $content); + $builder->addText(text: (string) $content); // Add file statistics $this->logger?->debug('Adding file statistics', [ @@ -204,7 +204,7 @@ private function addFileStatistics(string|\Stringable $content, string $resultPa 'filePath' => $outputPath, ]); - $builder->addFileStats($fileSize, $lineCount, $outputPath); + $builder->addFileStats(fileSize: $fileSize, lineCount: $lineCount, filePath: $outputPath); return $builder->build(); } catch (\Throwable $e) { diff --git a/src/Document/Compiler/Error/ErrorCollection.php b/src/Document/Compiler/Error/ErrorCollection.php index 226cc5ca..b575de61 100644 --- a/src/Document/Compiler/Error/ErrorCollection.php +++ b/src/Document/Compiler/Error/ErrorCollection.php @@ -40,7 +40,7 @@ public function hasErrors(): bool */ public function count(): int { - return \count($this->errors); + return \count(value: $this->errors); } /** @@ -48,14 +48,14 @@ public function count(): int */ public function getIterator(): \Traversable { - return new \ArrayIterator($this->errors); + return new \ArrayIterator(array: $this->errors); } public function jsonSerialize(): array { return \array_map( - static fn(\Stringable|string $error): string => (string) $error, - $this->errors, + callback: static fn(\Stringable|string $error): string => (string) $error, + array: $this->errors, ); } } diff --git a/src/Document/Compiler/Error/SourceError.php b/src/Document/Compiler/Error/SourceError.php index 63e7f7af..660da5c0 100644 --- a/src/Document/Compiler/Error/SourceError.php +++ b/src/Document/Compiler/Error/SourceError.php @@ -21,7 +21,7 @@ public function __construct( */ public function getSourceDescription(): string { - $source = new \ReflectionClass($this->source); + $source = new \ReflectionClass(objectOrClass: $this->source); return $this->source->hasDescription() ? $this->source->getDescription() : $source->getShortName(); diff --git a/src/Document/Document.php b/src/Document/Document.php index 71ba48ba..bfe04700 100644 --- a/src/Document/Document.php +++ b/src/Document/Document.php @@ -60,7 +60,7 @@ public static function create( */ public function getErrors(): array { - return \array_values($this->errors); + return \array_values(array: $this->errors); } public function addError(string $error): self @@ -97,7 +97,7 @@ public function addModifier(Modifier ...$modifiers): self */ public function getModifiers(): array { - return \array_values($this->modifiers); + return \array_values(array: $this->modifiers); } /** @@ -131,7 +131,7 @@ public function getTags(bool $includeSources = true): array } } - return \array_values(\array_unique($this->tags)); + return \array_values(array: \array_unique(array: $this->tags)); } /** @@ -149,18 +149,18 @@ public function hasTags(): bool */ public function getSources(): array { - return \array_values($this->sources); + return \array_values(array: $this->sources); } public function jsonSerialize(): array { - return \array_filter([ + return \array_filter(array: [ 'description' => $this->description, 'outputPath' => $this->outputPath, 'overwrite' => $this->overwrite, 'sources' => $this->getSources(), 'modifiers' => $this->getModifiers(), 'tags' => $this->getTags(), - ], static fn($value) => $value !== null && $value !== []); + ], callback: static fn($value) => $value !== null && $value !== []); } } diff --git a/src/Document/DocumentConfigMerger.php b/src/Document/DocumentConfigMerger.php index 32d9750e..76998d74 100644 --- a/src/Document/DocumentConfigMerger.php +++ b/src/Document/DocumentConfigMerger.php @@ -47,6 +47,6 @@ protected function performMerge(array $mainSection, array $importedSection, Impo } // Convert back to numerically indexed array - return \array_values($indexedDocuments); + return \array_values(array: $indexedDocuments); } } diff --git a/src/Document/DocumentRegistry.php b/src/Document/DocumentRegistry.php index 9e229802..3d4d1c50 100644 --- a/src/Document/DocumentRegistry.php +++ b/src/Document/DocumentRegistry.php @@ -46,12 +46,12 @@ public function jsonSerialize(): array public function getIterator(): \Traversable { - return new \ArrayIterator($this->getItems()); + return new \ArrayIterator(array: $this->getItems()); } public function offsetExists(mixed $offset): bool { - return \array_key_exists($offset, $this->documents); + return \array_key_exists(key: $offset, array: $this->documents); } public function offsetGet(mixed $offset): mixed @@ -61,11 +61,11 @@ public function offsetGet(mixed $offset): mixed public function offsetSet(mixed $offset, mixed $value): void { - throw new \BadMethodCallException('Cannot set value directly. Use register() method.'); + throw new \BadMethodCallException(message: 'Cannot set value directly. Use register() method.'); } public function offsetUnset(mixed $offset): void { - throw new \BadMethodCallException('Cannot unset value directly.'); + throw new \BadMethodCallException(message: 'Cannot unset value directly.'); } } diff --git a/src/Document/DocumentsParserPlugin.php b/src/Document/DocumentsParserPlugin.php index 8bd4b07c..ec80c545 100644 --- a/src/Document/DocumentsParserPlugin.php +++ b/src/Document/DocumentsParserPlugin.php @@ -31,7 +31,7 @@ public function getConfigKey(): string public function supports(array $config): bool { - return isset($config['documents']) && \is_array($config['documents']); + return isset($config['documents']) && \is_array(value: $config['documents']); } public function updateConfig(array $config, string $rootPath): array @@ -42,7 +42,7 @@ public function updateConfig(array $config, string $rootPath): array public function parse(array $config, string $rootPath): ?RegistryInterface { - if (!$this->supports($config)) { + if (!$this->supports(config: $config)) { return null; } @@ -51,20 +51,20 @@ public function parse(array $config, string $rootPath): ?RegistryInterface foreach ($config['documents'] as $index => $docData) { if (!isset($docData['description'], $docData['outputPath'])) { throw new \RuntimeException( - \sprintf('Document at index %d must have "description" and "outputPath"', $index), + message: \sprintf('Document at index %d must have "description" and "outputPath"', $index), ); } // Parse document modifiers if present $documentModifiers = []; - if (isset($docData['modifiers']) && \is_array($docData['modifiers'])) { - $documentModifiers = $this->parseModifiers($docData['modifiers']); + if (isset($docData['modifiers']) && \is_array(value: $docData['modifiers'])) { + $documentModifiers = $this->parseModifiers(modifiersConfig: $docData['modifiers']); } // Parse document tags if present $documentTags = []; - if (isset($docData['tags']) && \is_array($docData['tags'])) { - $documentTags = \array_map(\strval(...), $docData['tags']); + if (isset($docData['tags']) && \is_array(value: $docData['tags'])) { + $documentTags = \array_map(callback: \strval(...), array: $docData['tags']); } $document = Document::create( @@ -75,7 +75,7 @@ public function parse(array $config, string $rootPath): ?RegistryInterface tags: $documentTags, ); - if (isset($docData['sources']) && \is_array($docData['sources'])) { + if (isset($docData['sources']) && \is_array(value: $docData['sources'])) { foreach ($docData['sources'] as $sourceIndex => $sourceData) { try { $this->logger?->debug( @@ -102,7 +102,7 @@ public function parse(array $config, string $rootPath): ?RegistryInterface $document->addSource($this->sources->create($type, $sourceData)); } catch (\RuntimeException $e) { - $document->addError($e->getMessage()); + $document->addError(error: $e->getMessage()); $this->logger?->error( \sprintf('Failed to create source at index %d: %s', $sourceIndex, $e->getMessage()), [ @@ -114,7 +114,7 @@ public function parse(array $config, string $rootPath): ?RegistryInterface } } - $registry->register($document); + $registry->register(document: $document); } return $registry; @@ -127,6 +127,6 @@ public function parse(array $config, string $rootPath): ?RegistryInterface */ private function parseModifiers(array $modifiersConfig): array { - return $this->modifierResolver->resolveAll($modifiersConfig); + return $this->modifierResolver->resolveAll(references: $modifiersConfig); } } diff --git a/src/Lib/BinaryUpdater/BinaryUpdater.php b/src/Lib/BinaryUpdater/BinaryUpdater.php index f60a2fa3..636896a4 100644 --- a/src/Lib/BinaryUpdater/BinaryUpdater.php +++ b/src/Lib/BinaryUpdater/BinaryUpdater.php @@ -36,7 +36,7 @@ public function update(string $sourcePath, string $targetPath, bool $createDirec // Create the target directory if needed if ($createDirectory) { - $targetDir = \dirname($targetPath); + $targetDir = \dirname(path: $targetPath); $this->files->ensureDirectory($targetDir); } @@ -54,12 +54,12 @@ public function update(string $sourcePath, string $targetPath, bool $createDirec // Write to target if (!$this->files->write($targetPath, $content)) { - throw new \RuntimeException(\sprintf("Failed to write to target file: %s", $targetPath)); + throw new \RuntimeException(message: \sprintf("Failed to write to target file: %s", $targetPath)); } // Make executable (except on Windows) if (\PHP_OS_FAMILY !== 'Windows') { - \chmod($targetPath, 0755); + \chmod(filename: $targetPath, permissions: 0755); } $this->logger?->info("Direct update successful"); diff --git a/src/Lib/BinaryUpdater/Strategy/UnixUpdateStrategy.php b/src/Lib/BinaryUpdater/Strategy/UnixUpdateStrategy.php index 7209f451..4067125b 100644 --- a/src/Lib/BinaryUpdater/Strategy/UnixUpdateStrategy.php +++ b/src/Lib/BinaryUpdater/Strategy/UnixUpdateStrategy.php @@ -24,7 +24,7 @@ public function update(string $sourcePath, string $targetPath): bool // Create the update script $this->logger?->info("Creating Unix update script..."); - $scriptPath = $this->createUpdateScript($sourcePath, $targetPath); + $scriptPath = $this->createUpdateScript(sourcePath: $sourcePath, targetPath: $targetPath); if ($scriptPath === null) { $this->logger?->error("Failed to create Unix update script"); @@ -35,7 +35,7 @@ public function update(string $sourcePath, string $targetPath): bool // Make the script executable $this->logger?->info("Setting executable permissions on script"); - if (!\chmod($scriptPath, 0755)) { + if (!\chmod(filename: $scriptPath, permissions: 0755)) { $this->logger?->error("Failed to set executable permissions on script"); return false; } @@ -43,7 +43,7 @@ public function update(string $sourcePath, string $targetPath): bool // Run the script in the background and continue after PHP exits $command = \sprintf( 'nohup %s > /dev/null 2>&1 & echo $!', - \escapeshellarg($scriptPath), + \escapeshellarg(arg: $scriptPath), ); $this->logger?->info("Executing update script in background with command: {$command}"); @@ -51,10 +51,10 @@ public function update(string $sourcePath, string $targetPath): bool // Execute the command and capture the process ID $output = []; $resultCode = 0; - \exec($command, $output, $resultCode); + \exec(command: $command, output: $output, result_code: $resultCode); // If we got a process ID and the command executed successfully, consider it a success - $success = $resultCode === 0 && !empty($output[0]) && \is_numeric($output[0]); + $success = $resultCode === 0 && !empty($output[0]) && \is_numeric(value: $output[0]); if ($success) { $this->logger?->info("Successfully started background update process with PID: {$output[0]}"); @@ -78,29 +78,29 @@ private function createUpdateScript(string $sourcePath, string $targetPath): ?st $scriptContent = <</dev/null; then # Make the file executable @@ -113,17 +113,17 @@ private function createUpdateScript(string $sourcePath, string $targetPath): ?st ATTEMPT=\$((ATTEMPT+1)) fi done - + # Clean up the temporary source file rm -f "\$SOURCE" rm -f "$scriptPath" - + # Exit with the appropriate status if [ \$SUCCESS -eq 0 ]; then echo "Update failed after \$MAX_ATTEMPTS attempts." exit 1 fi - + exit 0 BASH; diff --git a/src/Lib/BinaryUpdater/Strategy/WindowsUpdateStrategy.php b/src/Lib/BinaryUpdater/Strategy/WindowsUpdateStrategy.php index d31084b1..53d20f9e 100644 --- a/src/Lib/BinaryUpdater/Strategy/WindowsUpdateStrategy.php +++ b/src/Lib/BinaryUpdater/Strategy/WindowsUpdateStrategy.php @@ -24,7 +24,7 @@ public function update(string $sourcePath, string $targetPath): bool // Create the update script $this->logger?->info("Creating Windows batch script..."); - $scriptPath = $this->createUpdateScript($sourcePath, $targetPath); + $scriptPath = $this->createUpdateScript(sourcePath: $sourcePath, targetPath: $targetPath); if ($scriptPath === null) { $this->logger?->error("Failed to create Windows batch script"); @@ -36,7 +36,7 @@ public function update(string $sourcePath, string $targetPath): bool // Run the script in the background $command = \sprintf( 'start /b "" %s', - \escapeshellarg($scriptPath), + \escapeshellarg(arg: $scriptPath), ); $this->logger?->info("Executing batch script in background with command: {$command}"); @@ -44,7 +44,7 @@ public function update(string $sourcePath, string $targetPath): bool // Execute the command $output = []; $resultCode = 0; - \exec($command, $output, $resultCode); + \exec(command: $command, output: $output, result_code: $resultCode); $success = $resultCode === 0; @@ -69,10 +69,10 @@ private function createUpdateScript(string $sourcePath, string $targetPath): ?st $this->logger?->info("Generated temporary script path: {$scriptPath}"); // Convert paths to Windows-style - $sourcePath = \str_replace('/', '\\', $sourcePath); - $targetPath = \str_replace('/', '\\', $targetPath); - $targetDir = \str_replace('/', '\\', \dirname($targetPath)); - $scriptPathWin = \str_replace('/', '\\', $scriptPath); + $sourcePath = \str_replace(search: '/', replace: '\\', subject: $sourcePath); + $targetPath = \str_replace(search: '/', replace: '\\', subject: $targetPath); + $targetDir = \str_replace(search: '/', replace: '\\', subject: \dirname(path: $targetPath)); + $scriptPathWin = \str_replace(search: '/', replace: '\\', subject: $scriptPath); $this->logger?->debug("Windows paths: source={$sourcePath}, target={$targetPath}, target_dir={$targetDir}"); @@ -80,28 +80,28 @@ private function createUpdateScript(string $sourcePath, string $targetPath): ?st @echo off rem Wait for parent process to exit timeout /t 1 /nobreak > nul - + rem Define paths set SOURCE={$sourcePath} set TARGET={$targetPath} set TARGET_DIR={$targetDir} - + echo Starting update process for %TARGET% - + rem Create the target directory if it doesn't exist if not exist "%TARGET_DIR%" mkdir "%TARGET_DIR%" - + rem Try to update the file with multiple attempts set MAX_ATTEMPTS=10 set ATTEMPT=1 set SUCCESS=0 - + :LOOP if %ATTEMPT% gtr %MAX_ATTEMPTS% goto FAILED if %SUCCESS% equ 1 goto SUCCESS - + echo Attempt %ATTEMPT%: Trying to update %TARGET% - + rem Try to copy the file copy /Y "%SOURCE%" "%TARGET%" > nul 2>&1 if %ERRORLEVEL% equ 0 ( @@ -113,19 +113,19 @@ private function createUpdateScript(string $sourcePath, string $targetPath): ?st set /a ATTEMPT+=1 goto LOOP ) - + :FAILED echo Update failed after %MAX_ATTEMPTS% attempts. goto CLEANUP - + :SUCCESS echo Update successful! - + :CLEANUP rem Clean up temporary files del "%SOURCE%" > nul 2>&1 del "{$scriptPathWin}" > nul 2>&1 - + if %SUCCESS% equ 0 exit /b 1 exit /b 0 BATCH; diff --git a/src/Lib/BinaryUpdater/UpdaterFactory.php b/src/Lib/BinaryUpdater/UpdaterFactory.php index 46187f3a..c179af45 100644 --- a/src/Lib/BinaryUpdater/UpdaterFactory.php +++ b/src/Lib/BinaryUpdater/UpdaterFactory.php @@ -30,8 +30,8 @@ public function createStrategy(): UpdateStrategyInterface { // Create the appropriate strategy based on the operating system return match (\PHP_OS_FAMILY) { - 'Windows' => new WindowsUpdateStrategy($this->files, $this->logger), - default => new UnixUpdateStrategy($this->files, $this->logger), + 'Windows' => new WindowsUpdateStrategy(files: $this->files, logger: $this->logger), + default => new UnixUpdateStrategy(files: $this->files, logger: $this->logger), }; } } diff --git a/src/Lib/ComposerClient/FileSystemComposerClient.php b/src/Lib/ComposerClient/FileSystemComposerClient.php index e77c11cf..82598f64 100644 --- a/src/Lib/ComposerClient/FileSystemComposerClient.php +++ b/src/Lib/ComposerClient/FileSystemComposerClient.php @@ -24,27 +24,27 @@ public function __construct( public function loadComposerData(string $path): array { // If path is a directory, append composer.json - if (\is_dir($path)) { - $path = \rtrim($path, '/') . '/composer.json'; + if (\is_dir(filename: $path)) { + $path = \rtrim(string: $path, characters: '/') . '/composer.json'; } // Check if composer.json exists if (!$this->files->exists($path)) { $this->logger?->error('composer.json not found', ['path' => $path]); - throw ComposerNotFoundException::fileNotFound($path); + throw ComposerNotFoundException::fileNotFound(path: $path); } // Read composer.json $composerJson = $this->files->read($path); // Parse composer.json - $composerData = \json_decode($composerJson, true); - if (!\is_array($composerData) || \json_last_error() !== JSON_ERROR_NONE) { + $composerData = \json_decode(json: $composerJson, associative: true); + if (!\is_array(value: $composerData) || \json_last_error() !== JSON_ERROR_NONE) { $this->logger?->error('Failed to parse composer.json', [ 'path' => $path, 'error' => \json_last_error_msg(), ]); - throw ComposerNotFoundException::cannotParse($path, \json_last_error_msg()); + throw ComposerNotFoundException::cannotParse(path: $path, reason: \json_last_error_msg()); } return $composerData; @@ -52,7 +52,7 @@ public function loadComposerData(string $path): array public function tryLoadComposerLock(string $path): ?array { - $lockPath = \rtrim($path, '/') . '/composer.lock'; + $lockPath = \rtrim(string: $path, characters: '/') . '/composer.lock'; if (!$this->files->exists($lockPath)) { $this->logger?->info('composer.lock not found', ['path' => $lockPath]); @@ -71,8 +71,8 @@ public function tryLoadComposerLock(string $path): ?array } // Parse composer.lock - $lockData = \json_decode($lockJson, true); - if (!\is_array($lockData) || \json_last_error() !== JSON_ERROR_NONE) { + $lockData = \json_decode(json: $lockJson, associative: true); + if (!\is_array(value: $lockData) || \json_last_error() !== JSON_ERROR_NONE) { $this->logger?->warning('Failed to parse composer.lock', [ 'path' => $lockPath, 'error' => \json_last_error_msg(), @@ -86,7 +86,7 @@ public function tryLoadComposerLock(string $path): ?array public function getVendorDir(array $composerData, string $basePath): string { // Check if composer.json has a custom vendor-dir configuration - if (isset($composerData['config']['vendor-dir']) && \is_string($composerData['config']['vendor-dir'])) { + if (isset($composerData['config']['vendor-dir']) && \is_string(value: $composerData['config']['vendor-dir'])) { return $composerData['config']['vendor-dir']; } @@ -94,7 +94,7 @@ public function getVendorDir(array $composerData, string $basePath): string $defaultVendorDir = 'vendor'; $vendorPath = $basePath . '/' . $defaultVendorDir; - if (\is_dir($vendorPath)) { + if (\is_dir(filename: $vendorPath)) { return $defaultVendorDir; } @@ -102,7 +102,7 @@ public function getVendorDir(array $composerData, string $basePath): string $possibleVendorDirs = ['vendor', 'vendors', 'lib', 'libs', 'packages', 'deps']; foreach ($possibleVendorDirs as $dir) { - if (\is_dir($basePath . '/' . $dir)) { + if (\is_dir(filename: $basePath . '/' . $dir)) { $this->logger?->info('Found alternative vendor directory', ['directory' => $dir]); return $dir; } diff --git a/src/Lib/Content/Block/FileStatsBlock.php b/src/Lib/Content/Block/FileStatsBlock.php index 5e624570..31e11319 100644 --- a/src/Lib/Content/Block/FileStatsBlock.php +++ b/src/Lib/Content/Block/FileStatsBlock.php @@ -45,14 +45,14 @@ public function formatSize(int $bytes): string $units = ['B', 'KB', 'MB', 'GB']; $i = 0; - while ($bytes >= 1024 && $i < \count($units) - 1) { + while ($bytes >= 1024 && $i < \count(value: $units) - 1) { $bytes = (float) $bytes / 1024.0; $i++; } // Ensure $i is within bounds - $i = \min($i, \count($units) - 1); + $i = \min($i, \count(value: $units) - 1); - return (string) \round($bytes, 2) . ' ' . $units[$i]; + return (string) \round(num: $bytes, precision: 2) . ' ' . $units[$i]; } } diff --git a/src/Lib/Content/Block/TextBlock.php b/src/Lib/Content/Block/TextBlock.php index c7a76ac8..b85ffe01 100644 --- a/src/Lib/Content/Block/TextBlock.php +++ b/src/Lib/Content/Block/TextBlock.php @@ -23,7 +23,7 @@ public function render(RendererInterface $renderer): string public function getTag(): string { - return \trim($this->tag); + return \trim(string: $this->tag); } public function hasTag(): bool diff --git a/src/Lib/Content/ContentBuilder.php b/src/Lib/Content/ContentBuilder.php index 301e4081..c9fd6896 100644 --- a/src/Lib/Content/ContentBuilder.php +++ b/src/Lib/Content/ContentBuilder.php @@ -68,7 +68,7 @@ public function getRenderer(): RendererInterface */ public function addBlock(BlockInterface $block): self { - $this->content->addBlock($block); + $this->content->addBlock(block: $block); return $this; } @@ -80,7 +80,7 @@ public function addBlock(BlockInterface $block): self */ public function addTitle(string $title, int $level = 1): self { - return $this->addBlock(new TitleBlock($title, $level)); + return $this->addBlock(block: new TitleBlock(content: $title, level: $level)); } /** @@ -90,7 +90,7 @@ public function addTitle(string $title, int $level = 1): self */ public function addText(string $text): self { - return $this->addBlock(new TextBlock($text)); + return $this->addBlock(block: new TextBlock(content: $text)); } /** @@ -100,7 +100,7 @@ public function addText(string $text): self */ public function addDescription(string $description): self { - return $this->addBlock(new DescriptionBlock($description)); + return $this->addBlock(block: new DescriptionBlock(content: $description)); } /** @@ -111,7 +111,7 @@ public function addDescription(string $description): self */ public function addCodeBlock(string $code, ?string $language = null, ?string $path = null): self { - return $this->addBlock(new CodeBlock($code, $language, $path)); + return $this->addBlock(block: new CodeBlock(content: $code, language: $language, filepath: $path)); } /** @@ -121,7 +121,7 @@ public function addCodeBlock(string $code, ?string $language = null, ?string $pa */ public function addTreeView(string $treeView): self { - return $this->addBlock(new TreeViewBlock($treeView)); + return $this->addBlock(block: new TreeViewBlock(content: $treeView)); } /** @@ -133,7 +133,7 @@ public function addTreeView(string $treeView): self */ public function addFileStats(int $fileSize, int $lineCount, ?string $filePath = null): self { - return $this->addBlock(new FileStatsBlock('', $fileSize, $lineCount, $filePath)); + return $this->addBlock(block: new FileStatsBlock(content: '', fileSize: $fileSize, lineCount: $lineCount, filePath: $filePath)); } /** @@ -144,7 +144,7 @@ public function addFileStats(int $fileSize, int $lineCount, ?string $filePath = */ public function addSeparator(string $separator = '-', int $length = 60): self { - return $this->addBlock(new SeparatorBlock($separator, $length)); + return $this->addBlock(block: new SeparatorBlock(content: $separator, length: $length)); } /** @@ -154,7 +154,7 @@ public function addSeparator(string $separator = '-', int $length = 60): self */ public function addComment(string $comment): self { - return $this->addBlock(new CommentBlock($comment)); + return $this->addBlock(block: new CommentBlock(content: $comment)); } /** @@ -163,7 +163,7 @@ public function addComment(string $comment): self public function merge(self $builder): self { foreach ($builder->content->getBlocks() as $block) { - $this->addBlock($block); + $this->addBlock(block: $block); } return $this; @@ -176,11 +176,11 @@ public function merge(self $builder): self */ public function build(): string { - return $this->content->render($this->renderer); + return $this->content->render(renderer: $this->renderer); } public function __toString(): string { - return (string) \preg_replace("/(\r\n|\n)+$/", '', $this->build()); + return (string) \preg_replace(pattern: "/(\r\n|\n)+$/", replacement: '', subject: $this->build()); } } diff --git a/src/Lib/Content/ContentBuilderFactory.php b/src/Lib/Content/ContentBuilderFactory.php index 6a6178e0..e8bc7b57 100644 --- a/src/Lib/Content/ContentBuilderFactory.php +++ b/src/Lib/Content/ContentBuilderFactory.php @@ -15,6 +15,6 @@ public function __construct( public function create(?RendererInterface $renderer = null): ContentBuilder { - return new ContentBuilder($renderer ?? $this->defaultRenderer); + return new ContentBuilder(renderer: $renderer ?? $this->defaultRenderer); } } diff --git a/src/Lib/Content/Renderer/AbstractRenderer.php b/src/Lib/Content/Renderer/AbstractRenderer.php index 34c2212a..199db0f9 100644 --- a/src/Lib/Content/Renderer/AbstractRenderer.php +++ b/src/Lib/Content/Renderer/AbstractRenderer.php @@ -20,7 +20,7 @@ public function renderContent(array $blocks): string continue; } - $content .= \preg_replace("/(\r\n|\n)+$/", "\n", $block->render($this)); + $content .= \preg_replace(pattern: "/(\r\n|\n)+$/", replacement: "\n", subject: $block->render($this)); } return $content; diff --git a/src/Lib/Content/Renderer/MarkdownRenderer.php b/src/Lib/Content/Renderer/MarkdownRenderer.php index 0dee2bb6..daf62b93 100644 --- a/src/Lib/Content/Renderer/MarkdownRenderer.php +++ b/src/Lib/Content/Renderer/MarkdownRenderer.php @@ -54,7 +54,7 @@ public function renderTitleBlock(TitleBlock $block): string } $level = $block->getLevel(); - $prefix = \str_repeat('#', \min(6, \max(1, $level))); + $prefix = \str_repeat(string: '#', times: \min(6, \max(1, $level))); return "{$prefix} " . $content . "\n\n"; } @@ -81,7 +81,7 @@ public function renderTreeViewBlock(TreeViewBlock $block): string public function renderFileStatsBlock(FileStatsBlock $block): string { $filePath = $block->getFilePath() ? "File: `{$block->getFilePath()}`\n" : ''; - $size = $block->formatSize($block->getFileSize()); + $size = $block->formatSize(bytes: $block->getFileSize()); $lineCount = $block->getLineCount(); return <<getLength()) . "\n\n"; + return \str_repeat(string: (string) $block, times: $block->getLength()) . "\n\n"; } public function renderCommentBlock(CommentBlock $block): string @@ -106,7 +106,7 @@ public function renderCommentBlock(CommentBlock $block): string return ''; } - $lines = \explode("\n", $content); + $lines = \explode(separator: "\n", string: $content); $result = ''; foreach ($lines as $line) { diff --git a/src/Lib/Context7Client/Context7Client.php b/src/Lib/Context7Client/Context7Client.php index df62f6fc..b0832c60 100644 --- a/src/Lib/Context7Client/Context7Client.php +++ b/src/Lib/Context7Client/Context7Client.php @@ -23,11 +23,11 @@ public function __construct( public function searchLibraries(string $query, int $maxResults = 2): LibrarySearchResult { - if (empty(\trim($query))) { - throw new \InvalidArgumentException('Search query cannot be empty'); + if (empty(\trim(string: $query))) { + throw new \InvalidArgumentException(message: 'Search query cannot be empty'); } - $url = self::API_BASE_URL . '/search?' . \http_build_query(['query' => $query]); + $url = self::API_BASE_URL . '/search?' . \http_build_query(data: ['query' => $query]); $this->logger->debug('Sending request to Context7 search API', [ 'url' => $url, @@ -42,17 +42,17 @@ public function searchLibraries(string $query, int $maxResults = 2): LibrarySear ]); if (!$response->isSuccess()) { - $this->handleErrorResponse($response->getStatusCode(), $query); + $this->handleErrorResponse(statusCode: $response->getStatusCode(), query: $query); } - $data = $response->getJson(true); + $data = $response->getJson(); $this->logger->info('Documentation libraries found', [ - 'count' => \count($data['results'] ?? []), + 'count' => \count(value: $data['results'] ?? []), 'query' => $query, ]); - return LibrarySearchResult::fromArray($data, $maxResults); + return LibrarySearchResult::fromArray(data: $data, maxResults: $maxResults); } catch (Context7ClientException $e) { // Re-throw our own exceptions throw $e; @@ -63,20 +63,20 @@ public function searchLibraries(string $query, int $maxResults = 2): LibrarySear 'trace' => $e->getTraceAsString(), ]); - throw Context7ClientException::searchFailed($query, 0); + throw Context7ClientException::searchFailed(query: $query, statusCode: 0); } } public function fetchLibraryDocumentation(string $libraryId, ?int $tokens = null, ?string $topic = null): string { - if (empty(\trim($libraryId))) { - throw new \InvalidArgumentException('Library ID cannot be empty'); + if (empty(\trim(string: $libraryId))) { + throw new \InvalidArgumentException(message: 'Library ID cannot be empty'); } // Remove leading slash from libraryId if present (as per JS reference) - $libraryId = \ltrim($libraryId, '/'); + $libraryId = \ltrim(string: $libraryId, characters: '/'); - $url = $this->buildDocumentationUrl($libraryId, $tokens, $topic); + $url = $this->buildDocumentationUrl(libraryId: $libraryId, tokens: $tokens, topic: $topic); $this->logger->debug('Fetching library documentation from Context7 API', [ 'libraryId' => $libraryId, @@ -93,21 +93,21 @@ public function fetchLibraryDocumentation(string $libraryId, ?int $tokens = null ]); if (!$response->isSuccess()) { - $this->handleDocumentationErrorResponse($response->getStatusCode(), $libraryId); + $this->handleDocumentationErrorResponse(statusCode: $response->getStatusCode(), libraryId: $libraryId); } $documentation = $response->getBody(); - if ($this->isEmptyDocumentation($documentation)) { + if ($this->isEmptyDocumentation(documentation: $documentation)) { $this->logger->warning('No documentation found for library', [ 'libraryId' => $libraryId, ]); - throw Context7ClientException::noDocumentationFound($libraryId); + throw Context7ClientException::noDocumentationFound(libraryId: $libraryId); } $this->logger->info('Library documentation fetched successfully', [ 'libraryId' => $libraryId, - 'documentationLength' => \strlen($documentation), + 'documentationLength' => \strlen(string: $documentation), ]); return $documentation; @@ -121,7 +121,7 @@ public function fetchLibraryDocumentation(string $libraryId, ?int $tokens = null 'trace' => $e->getTraceAsString(), ]); - throw Context7ClientException::documentationFetchFailed($libraryId, 0); + throw Context7ClientException::documentationFetchFailed(libraryId: $libraryId, statusCode: 0); } } @@ -138,7 +138,7 @@ private function buildDocumentationUrl(string $libraryId, ?int $tokens, ?string $params['topic'] = $topic; } - return $url . '?' . \http_build_query($params); + return $url . '?' . \http_build_query(data: $params); } private function handleErrorResponse(int $statusCode, string $query): void @@ -151,7 +151,7 @@ private function handleErrorResponse(int $statusCode, string $query): void match ($statusCode) { 429 => throw Context7ClientException::rateLimited(), 401 => throw Context7ClientException::unauthorized(), - default => throw Context7ClientException::searchFailed($query, $statusCode), + default => throw Context7ClientException::searchFailed(query: $query, statusCode: $statusCode), }; } @@ -165,8 +165,8 @@ private function handleDocumentationErrorResponse(int $statusCode, string $libra match ($statusCode) { 429 => throw Context7ClientException::rateLimited(), 401 => throw Context7ClientException::unauthorized(), - 404 => throw Context7ClientException::libraryNotFound($libraryId), - default => throw Context7ClientException::documentationFetchFailed($libraryId, $statusCode), + 404 => throw Context7ClientException::libraryNotFound(libraryId: $libraryId), + default => throw Context7ClientException::documentationFetchFailed(libraryId: $libraryId, statusCode: $statusCode), }; } diff --git a/src/Lib/Context7Client/Model/Library.php b/src/Lib/Context7Client/Model/Library.php index d8062860..b5b8f3b3 100644 --- a/src/Lib/Context7Client/Model/Library.php +++ b/src/Lib/Context7Client/Model/Library.php @@ -39,7 +39,7 @@ public function getUsage(): string { return \sprintf( "Use in your context config: { type: 'docs', library: '%s', topic: 'your-topic' }", - \ltrim($this->id, '/'), + \ltrim(string: $this->id, characters: '/'), ); } diff --git a/src/Lib/Context7Client/Model/LibrarySearchResult.php b/src/Lib/Context7Client/Model/LibrarySearchResult.php index 8ffd4a16..3c29b8b8 100644 --- a/src/Lib/Context7Client/Model/LibrarySearchResult.php +++ b/src/Lib/Context7Client/Model/LibrarySearchResult.php @@ -19,19 +19,19 @@ public function __construct( */ public static function fromArray(array $data, int $maxResults = 2): self { - if (!isset($data['results']) || !\is_array($data['results'])) { - throw new \InvalidArgumentException('Invalid search response format: missing results array'); + if (!isset($data['results']) || !\is_array(value: $data['results'])) { + throw new \InvalidArgumentException(message: 'Invalid search response format: missing results array'); } $libraries = []; - $results = \array_slice($data['results'], 0, \min(5, \max(1, $maxResults))); + $results = \array_slice(array: $data['results'], offset: 0, length: \min(5, \max(1, $maxResults))); foreach ($results as $libraryData) { - $libraries[] = Library::fromArray($libraryData); + $libraries[] = Library::fromArray(data: $libraryData); } return new self( - count: \count($libraries), + count: \count(value: $libraries), libraries: $libraries, ); } diff --git a/src/Lib/Finder/FinderResult.php b/src/Lib/Finder/FinderResult.php index 97187ce7..a87b1327 100644 --- a/src/Lib/Finder/FinderResult.php +++ b/src/Lib/Finder/FinderResult.php @@ -20,6 +20,6 @@ public function __construct( public function count(): int { - return \count($this->files); + return \count(value: $this->files); } } diff --git a/src/Lib/Git/Command.php b/src/Lib/Git/Command.php index 5c1f8c87..fde4d99a 100644 --- a/src/Lib/Git/Command.php +++ b/src/Lib/Git/Command.php @@ -25,33 +25,33 @@ public function __construct( */ public function getCommandParts(): array { - if (\is_array($this->command)) { + if (\is_array(value: $this->command)) { return $this->command; } - $command = \trim($this->command); + $command = \trim(string: $this->command); // If the command already starts with 'git', remove it - if (\str_starts_with($command, 'git ')) { - $command = \substr($command, 4); + if (\str_starts_with(haystack: $command, needle: 'git ')) { + $command = \substr(string: $command, offset: 4); } - return \array_filter(\explode(' ', $command)); + return \array_filter(array: \explode(separator: ' ', string: $command)); } public function __toString(): string { - if (\is_string($this->command)) { - $command = \trim($this->command); + if (\is_string(value: $this->command)) { + $command = \trim(string: $this->command); // If the command already starts with 'git', use it as is - if (\str_starts_with($command, 'git ')) { - $command = \substr($command, 4); + if (\str_starts_with(haystack: $command, needle: 'git ')) { + $command = \substr(string: $command, offset: 4); } return $command; } - return \implode(' ', $this->command); + return \implode(separator: ' ', array: $this->command); } } diff --git a/src/Lib/Git/CommandsExecutor.php b/src/Lib/Git/CommandsExecutor.php index b542ebb9..c6469cd6 100644 --- a/src/Lib/Git/CommandsExecutor.php +++ b/src/Lib/Git/CommandsExecutor.php @@ -31,61 +31,61 @@ public function __construct( public function executeString(Command $command): string { $repository = $command->repository; - $repositoryPath = $this->resolvePath($repository); + $repositoryPath = $this->resolvePath(repository: $repository); - if (!$this->isValidRepository($repositoryPath)) { + if (!$this->isValidRepository(repository: $repositoryPath)) { $this->logger?->error('Not a valid Git repository', [ 'repository' => $repositoryPath, ]); - throw new \InvalidArgumentException(\sprintf('"%s" is not a valid Git repository', $repositoryPath)); + throw new \InvalidArgumentException(message: \sprintf('"%s" is not a valid Git repository', $repositoryPath)); } $commandParts = ['git', ...$command->getCommandParts()]; $this->logger?->debug('Executing Git command', [ - 'command' => \implode(' ', $commandParts), + 'command' => \implode(separator: ' ', array: $commandParts), 'repository' => $repositoryPath, ]); try { - $process = new Process($commandParts, $repositoryPath); + $process = new Process(command: $commandParts, cwd: $repositoryPath); $process->run(); if (!$process->isSuccessful()) { $this->logger?->error('Git command failed', [ - 'command' => \implode(' ', $commandParts), + 'command' => \implode(separator: ' ', array: $commandParts), 'exitCode' => $process->getExitCode(), 'errorOutput' => $process->getErrorOutput(), ]); throw new GitCommandException( - \sprintf( + message: \sprintf( 'Git command "%s" failed with exit code %d: %s', - \implode(' ', $commandParts), + \implode(separator: ' ', array: $commandParts), $process->getExitCode(), $process->getErrorOutput(), ), - $process->getExitCode(), + code: $process->getExitCode(), ); } $this->logger?->debug('Git command executed successfully', [ - 'command' => \implode(' ', $commandParts), - 'outputLength' => \strlen($process->getOutput()), + 'command' => \implode(separator: ' ', array: $commandParts), + 'outputLength' => \strlen(string: $process->getOutput()), ]); return $process->getOutput(); } catch (ProcessFailedException $e) { $this->logger?->error('Git command process failed', [ - 'command' => \implode(' ', $commandParts), + 'command' => \implode(separator: ' ', array: $commandParts), 'error' => $e->getMessage(), ]); throw new GitCommandException( - \sprintf('Git command process failed: %s', $e->getMessage()), - $e->getCode(), - $e, + message: \sprintf('Git command process failed: %s', $e->getMessage()), + code: $e->getCode(), + previous: $e, ); } } @@ -101,9 +101,9 @@ public function isValidRepository(string $repository): bool return self::$validatedRepositories[$repository]; } - $repositoryPath = $this->resolvePath($repository); + $repositoryPath = $this->resolvePath(repository: $repository); - if (!\is_dir($repositoryPath)) { + if (!\is_dir(filename: $repositoryPath)) { $this->logger?->debug('Repository directory does not exist', [ 'repository' => $repository, ]); @@ -113,13 +113,13 @@ public function isValidRepository(string $repository): bool try { $process = new Process( - ['git', 'rev-parse', '--is-inside-work-tree'], - $repositoryPath, + command: ['git', 'rev-parse', '--is-inside-work-tree'], + cwd: $repositoryPath, ); $process->run(); - $isValid = $process->isSuccessful() && \trim($process->getOutput()) === 'true'; + $isValid = $process->isSuccessful() && \trim(string: $process->getOutput()) === 'true'; $this->logger?->debug('Repository validation result', [ 'repository' => $repository, @@ -144,19 +144,19 @@ public function applyPatch(string $filePath, string $patchContent): string { $rootPath = $this->dirs->getRootPath(); - if (!$this->isValidRepository((string) $rootPath)) { + if (!$this->isValidRepository(repository: (string) $rootPath)) { $this->logger?->error('Not a valid Git repository', [ 'repository' => (string) $rootPath, ]); - throw new \InvalidArgumentException(\sprintf('"%s" is not a valid Git repository', $rootPath)); + throw new \InvalidArgumentException(message: \sprintf('"%s" is not a valid Git repository', $rootPath)); } $file = $rootPath->join($filePath); // Ensure the file exists if (!$file->exists()) { - throw new GitCommandException(\sprintf('File "%s" does not exist', $filePath)); + throw new GitCommandException(message: \sprintf('File "%s" does not exist', $filePath)); } // Create a temporary file for the patch @@ -167,7 +167,7 @@ public function applyPatch(string $filePath, string $patchContent): string 'error' => $e->getMessage(), ]); - throw new GitCommandException('Failed to create temporary file for patch', 0, $e); + throw new GitCommandException(message: 'Failed to create temporary file for patch', previous: $e); } try { @@ -176,8 +176,8 @@ public function applyPatch(string $filePath, string $patchContent): string // Apply the patch using git apply command $process = new Process( - ['git', 'apply', '--whitespace=nowarn', $patchFile], - (string) $rootPath, + command: ['git', 'apply', '--whitespace=nowarn', $patchFile], + cwd: (string) $rootPath, ); $process->run(); @@ -185,8 +185,8 @@ public function applyPatch(string $filePath, string $patchContent): string // Check if the command was successful if (!$process->isSuccessful()) { throw new GitCommandException( - \sprintf('Failed to apply patch: %s', $process->getErrorOutput()), - $process->getExitCode(), + message: \sprintf('Failed to apply patch: %s', $process->getErrorOutput()), + code: $process->getExitCode(), ); } diff --git a/src/Lib/Git/Exception/GitClientException.php b/src/Lib/Git/Exception/GitClientException.php index bacb94fd..8119273e 100644 --- a/src/Lib/Git/Exception/GitClientException.php +++ b/src/Lib/Git/Exception/GitClientException.php @@ -23,7 +23,7 @@ public function __construct( 'Git command "%s" failed with exit code %d: %s', $command, $exitCode, - \implode("\n", $errorOutput), + \implode(separator: "\n", array: $errorOutput), ); parent::__construct($message, $exitCode); diff --git a/src/Lib/GithubClient/Architecture.php b/src/Lib/GithubClient/Architecture.php index 1ae39f97..6a50a058 100644 --- a/src/Lib/GithubClient/Architecture.php +++ b/src/Lib/GithubClient/Architecture.php @@ -11,13 +11,13 @@ enum Architecture: string public static function detect(): self { - $arch = \php_uname('m'); + $arch = \php_uname(mode: 'm'); - return match (\strtolower($arch)) { + return match (\strtolower(string: $arch)) { 'x86_64', 'amd64' => self::Amd64, 'aarch64', 'arm64' => self::Arm64, // Add more mappings as needed - default => throw new \RuntimeException('Unsupported architecture: ' . $arch), + default => throw new \RuntimeException(message: 'Unsupported architecture: ' . $arch), }; } } diff --git a/src/Lib/GithubClient/BinaryNameBuilder.php b/src/Lib/GithubClient/BinaryNameBuilder.php index 89e37aaa..01bda63d 100644 --- a/src/Lib/GithubClient/BinaryNameBuilder.php +++ b/src/Lib/GithubClient/BinaryNameBuilder.php @@ -21,7 +21,7 @@ public function buildPlatformSpecificName(string $baseName, string $version, string $type): string { if ($type === 'phar') { - return $this->buildGenericName($baseName, $type); + return $this->buildGenericName(baseName: $baseName, type: $type); } try { @@ -39,10 +39,10 @@ public function buildPlatformSpecificName(string $baseName, string $version, str $architecture->value, $extension, ), - default => throw new \InvalidArgumentException('Invalid type provided: ' . $type), + default => throw new \InvalidArgumentException(message: 'Invalid type provided: ' . $type), }; } catch (\Throwable $e) { - throw new \RuntimeException("Failed to build platform-specific binary name: {$e->getMessage()}", 0, $e); + throw new \RuntimeException(message: "Failed to build platform-specific binary name: {$e->getMessage()}", previous: $e); } } @@ -58,7 +58,7 @@ public function buildGenericName(string $baseName, string $type): string return match ($type) { 'phar' => "{$baseName}.phar", 'bin' => $baseName, - default => throw new \InvalidArgumentException('Invalid type provided: ' . $type), + default => throw new \InvalidArgumentException(message: 'Invalid type provided: ' . $type), }; } diff --git a/src/Lib/GithubClient/GithubClient.php b/src/Lib/GithubClient/GithubClient.php index a9c7c228..a4b31e31 100644 --- a/src/Lib/GithubClient/GithubClient.php +++ b/src/Lib/GithubClient/GithubClient.php @@ -26,11 +26,11 @@ public function getContents(GithubRepository $repository, string $path = ''): ar $url = \sprintf( '/repos/%s/contents/%s?ref=%s', $repository->repository, - $path ? \urlencode($path) : '', - \urlencode($repository->branch), + $path ? \urlencode(string: $path) : '', + \urlencode(string: $repository->branch), ); - $response = $this->sendRequest('GET', $url); + $response = $this->sendRequest(method: 'GET', path: $url); /** * Check if we got a single file or a directory @@ -47,14 +47,14 @@ public function getFileContent(GithubRepository $repository, string $path): stri $url = \sprintf( '/repos/%s/contents/%s?ref=%s', $repository->repository, - \urlencode($path), - \urlencode($repository->branch), + \urlencode(string: $path), + \urlencode(string: $repository->branch), ); - $response = $this->sendRequest('GET', $url); + $response = $this->sendRequest(method: 'GET', path: $url); if (!isset($response['content'])) { - throw new \RuntimeException("Could not get content for file: $path"); + throw new \RuntimeException(message: "Could not get content for file: $path"); } // GitHub API returns base64 encoded content @@ -69,9 +69,9 @@ public function setToken(?string $token): void public function getReleaseManager(GithubRepository $repository): ReleaseManager { return new ReleaseManager( - $this->httpClient, - $repository, - $this->token, + httpClient: $this->httpClient, + repository: $repository, + token: $this->token, ); } @@ -105,14 +105,14 @@ private function sendRequest(string $method, string $path): array // Check for success status code if (!$response->isSuccess()) { throw new \RuntimeException( - "GitHub API request failed with status code " . $response->getStatusCode(), + message: "GitHub API request failed with status code " . $response->getStatusCode(), ); } // Parse JSON response return $response->getJson(); } catch (\Throwable $e) { - throw new \RuntimeException('GitHub API request failed: ' . $e->getMessage(), 0, $e); + throw new \RuntimeException(message: 'GitHub API request failed: ' . $e->getMessage(), previous: $e); } } } diff --git a/src/Lib/GithubClient/Model/GithubRepository.php b/src/Lib/GithubClient/Model/GithubRepository.php index af9380b3..754675db 100644 --- a/src/Lib/GithubClient/Model/GithubRepository.php +++ b/src/Lib/GithubClient/Model/GithubRepository.php @@ -14,9 +14,9 @@ public function __construct( public string $repository, public string $branch = 'main', ) { - if (!\preg_match('/^([^\/]+)\/([^\/]+)$/', $repository)) { + if (!\preg_match(pattern: '/^([^\/]+)\/([^\/]+)$/', subject: $repository)) { throw new \InvalidArgumentException( - "Invalid repository format: $repository. Expected format: owner/repo", + message: "Invalid repository format: $repository. Expected format: owner/repo", ); } } diff --git a/src/Lib/GithubClient/Model/Release.php b/src/Lib/GithubClient/Model/Release.php index 7cfa8ec8..297e63fe 100644 --- a/src/Lib/GithubClient/Model/Release.php +++ b/src/Lib/GithubClient/Model/Release.php @@ -34,7 +34,7 @@ public static function fromApiResponse(array $data): self $assets = []; // Process assets to create a map of filename => download URL - if (isset($data['assets']) && \is_array($data['assets'])) { + if (isset($data['assets']) && \is_array(value: $data['assets'])) { foreach ($data['assets'] as $asset) { if (isset($asset['name'], $asset['browser_download_url'])) { $assets[(string) $asset['name']] = (string) $asset['browser_download_url']; @@ -56,7 +56,7 @@ public static function fromApiResponse(array $data): self */ public function getVersion(): string { - return \ltrim($this->tagName, 'v'); + return \ltrim(string: $this->tagName, characters: 'v'); } /** @@ -65,7 +65,7 @@ public function getVersion(): string public function isNewerThan(string $currentVersion): bool { // Clean up versions for comparison - $currentVersion = \ltrim($currentVersion, 'v'); + $currentVersion = \ltrim(string: $currentVersion, characters: 'v'); $releaseVersion = $this->getVersion(); return \version_compare($currentVersion, $releaseVersion, '<'); diff --git a/src/Lib/GithubClient/Platform.php b/src/Lib/GithubClient/Platform.php index 979e31e0..8df151b4 100644 --- a/src/Lib/GithubClient/Platform.php +++ b/src/Lib/GithubClient/Platform.php @@ -16,7 +16,7 @@ public static function detect(): self 'Linux' => self::Linux, 'Darwin' => self::Macos, 'Windows' => self::Windows, - default => throw new \RuntimeException('Unsupported platform: ' . PHP_OS_FAMILY), + default => throw new \RuntimeException(message: 'Unsupported platform: ' . PHP_OS_FAMILY), }; } diff --git a/src/Lib/GithubClient/ReleaseManager.php b/src/Lib/GithubClient/ReleaseManager.php index ba305660..4a5d8090 100644 --- a/src/Lib/GithubClient/ReleaseManager.php +++ b/src/Lib/GithubClient/ReleaseManager.php @@ -42,15 +42,15 @@ public function getLatestRelease(): Release if (!$response->isSuccess()) { throw new \RuntimeException( - "Failed to fetch latest release. Server returned status code {$response->getStatusCode()}", + message: "Failed to fetch latest release. Server returned status code {$response->getStatusCode()}", ); } try { $data = $response->getJson(); - return Release::fromApiResponse($data); + return Release::fromApiResponse(data: $data); } catch (HttpException $e) { - throw new \RuntimeException("Failed to parse GitHub response: {$e->getMessage()}", 0, $e); + throw new \RuntimeException(message: "Failed to parse GitHub response: {$e->getMessage()}", previous: $e); } } @@ -62,11 +62,11 @@ public function downloadBinary(string $version, string $binaryName, string $type { // First try platform-specific binary try { - $fileName = $this->binaryNameBuilder->buildPlatformSpecificName($binaryName, $version, $type); + $fileName = $this->binaryNameBuilder->buildPlatformSpecificName(baseName: $binaryName, version: $version, type: $type); $this->logger?->info("Attempting to download platform-specific binary: {$fileName}"); - $assetUrl = $this->getAssetUrlOrFail($fileName); - $this->downloadAsset($assetUrl, $destinationPath); + $assetUrl = $this->getAssetUrlOrFail(fileName: $fileName); + $this->downloadAsset(assetUrl: $assetUrl, destinationPath: $destinationPath); $this->logger?->info("Successfully downloaded platform-specific binary: {$fileName}"); return true; @@ -75,17 +75,17 @@ public function downloadBinary(string $version, string $binaryName, string $type // Fall back to generic binary try { - $fileName = $this->binaryNameBuilder->buildGenericName($binaryName, $type); + $fileName = $this->binaryNameBuilder->buildGenericName(baseName: $binaryName, type: $type); $this->logger?->info("Falling back to generic binary: {$fileName}"); - $assetUrl = $this->getAssetUrlOrFail($fileName); - $this->downloadAsset($assetUrl, $destinationPath); + $assetUrl = $this->getAssetUrlOrFail(fileName: $fileName); + $this->downloadAsset(assetUrl: $assetUrl, destinationPath: $destinationPath); $this->logger?->info("Successfully downloaded generic binary: {$fileName}"); return true; } catch (\Throwable $e2) { $this->logger?->error("Failed to download generic binary: {$e2->getMessage()}"); - throw new \RuntimeException("Failed to download binary: {$e2->getMessage()}", 0, $e2); + throw new \RuntimeException(message: "Failed to download binary: {$e2->getMessage()}", previous: $e2); } } } @@ -102,19 +102,19 @@ private function downloadAsset(string $assetUrl, string $destinationPath): void if (!$response->isSuccess()) { throw new \RuntimeException( - "Failed to download asset. Server returned status code {$response->getStatusCode()}", + message: "Failed to download asset. Server returned status code {$response->getStatusCode()}", ); } // Write the file - if (!\file_put_contents($destinationPath, $response->getBody())) { - throw new \RuntimeException("Failed to write file: {$destinationPath}"); + if (!\file_put_contents(filename: $destinationPath, data: $response->getBody())) { + throw new \RuntimeException(message: "Failed to write file: {$destinationPath}"); } // Make the file executable if it's not a Windows system if (\PHP_OS_FAMILY !== 'Windows') { - if (!\chmod($destinationPath, 0755)) { - throw new \RuntimeException("Failed to set executable permissions on the file: {$destinationPath}"); + if (!\chmod(filename: $destinationPath, permissions: 0755)) { + throw new \RuntimeException(message: "Failed to set executable permissions on the file: {$destinationPath}"); } } } @@ -129,10 +129,10 @@ private function downloadAsset(string $assetUrl, string $destinationPath): void private function getAssetUrlOrFail(string $fileName): string { $release = $this->getLatestRelease(); - $assetUrl = $release->getAssetUrl($fileName); + $assetUrl = $release->getAssetUrl(fileName: $fileName); if ($assetUrl === null) { - throw new \RuntimeException("Could not find asset '{$fileName}' in release {$release->getVersion()}"); + throw new \RuntimeException(message: "Could not find asset '{$fileName}' in release {$release->getVersion()}"); } return $assetUrl; diff --git a/src/Lib/GitlabClient/GitlabClient.php b/src/Lib/GitlabClient/GitlabClient.php index bbdd27dc..9ed766b3 100644 --- a/src/Lib/GitlabClient/GitlabClient.php +++ b/src/Lib/GitlabClient/GitlabClient.php @@ -43,7 +43,7 @@ public function getContents(GitlabRepository $repository, string $path = ''): ar ]); // Format URL for GitLab API v4 - $url = $this->buildApiUrl("/projects/{$repository->projectId}/repository/tree", [ + $url = $this->buildApiUrl(path: "/projects/{$repository->projectId}/repository/tree", queryParams: [ 'ref' => $repository->branch, 'path' => $path, 'recursive' => 'false', @@ -53,19 +53,19 @@ public function getContents(GitlabRepository $repository, string $path = ''): ar 'url' => $url, ]); - $response = $this->makeApiRequest($url); - $items = \json_decode($response, true); + $response = $this->makeApiRequest(url: $url); + $items = \json_decode(json: $response, associative: true); - if (!\is_array($items)) { + if (!\is_array(value: $items)) { $errorMessage = "Failed to parse GitLab API response for path: $path"; $this->logger?->error($errorMessage, [ 'response' => $response, ]); - throw new \RuntimeException($errorMessage); + throw new \RuntimeException(message: $errorMessage); } $this->logger?->debug('Got repository contents', [ - 'itemCount' => \count($items), + 'itemCount' => \count(value: $items), ]); return $items; @@ -80,7 +80,7 @@ public function getFileContent(GitlabRepository $repository, string $path): stri ]); // Format URL for GitLab API v4 - $url = $this->buildApiUrl("/projects/{$repository->projectId}/repository/files/" . \rawurlencode($path), [ + $url = $this->buildApiUrl(path: "/projects/{$repository->projectId}/repository/files/" . \rawurlencode(string: $path), queryParams: [ 'ref' => $repository->branch, ]); @@ -88,15 +88,15 @@ public function getFileContent(GitlabRepository $repository, string $path): stri 'url' => $url, ]); - $response = $this->makeApiRequest($url); - $data = \json_decode($response, true); + $response = $this->makeApiRequest(url: $url); + $data = \json_decode(json: $response, associative: true); - if (!\is_array($data) || !isset($data['content'])) { + if (!\is_array(value: $data) || !isset($data['content'])) { $errorMessage = "Failed to get file content for path: $path"; $this->logger?->error($errorMessage, [ 'response' => $response, ]); - throw new \RuntimeException($errorMessage); + throw new \RuntimeException(message: $errorMessage); } // GitLab returns file content as base64 encoded @@ -105,11 +105,11 @@ public function getFileContent(GitlabRepository $repository, string $path): stri if ($content === false) { $errorMessage = "Failed to decode base64 content for path: $path"; $this->logger?->error($errorMessage); - throw new \RuntimeException($errorMessage); + throw new \RuntimeException(message: $errorMessage); } $this->logger?->debug('Got file content', [ - 'contentLength' => \strlen($content), + 'contentLength' => \strlen(string: $content), ]); return $content; @@ -128,14 +128,14 @@ public function setServerUrl(string $serverUrl): void $this->logger?->debug('Setting GitLab server URL', [ 'serverUrl' => $serverUrl, ]); - $this->serverUrl = \rtrim($serverUrl, '/'); + $this->serverUrl = \rtrim(string: $serverUrl, characters: '/'); } public function setHeaders(array $headers): void { $this->logger?->debug('Setting custom HTTP headers', [ - 'headerCount' => \count($headers), - 'headers' => \array_keys($headers), + 'headerCount' => \count(value: $headers), + 'headers' => \array_keys(array: $headers), ]); $this->headers = $headers; } @@ -152,7 +152,7 @@ private function buildApiUrl(string $path, array $queryParams = []): string $url = "{$this->serverUrl}/api/v4{$path}"; if (!empty($queryParams)) { - $url .= '?' . \http_build_query($queryParams); + $url .= '?' . \http_build_query(data: $queryParams); } return $url; @@ -180,7 +180,7 @@ private function makeApiRequest(string $url): string 'statusCode' => $response->getStatusCode(), 'response' => $response->getBody(), ]); - throw new \RuntimeException($errorMessage); + throw new \RuntimeException(message: $errorMessage); } return $response->getBody(); @@ -190,7 +190,7 @@ private function makeApiRequest(string $url): string 'url' => $url, 'exception' => $e, ]); - throw new \RuntimeException($errorMessage, 0, $e); + throw new \RuntimeException(message: $errorMessage, previous: $e); } } diff --git a/src/Lib/GitlabClient/Model/GitlabRepository.php b/src/Lib/GitlabClient/Model/GitlabRepository.php index 101a174a..5b4051a4 100644 --- a/src/Lib/GitlabClient/Model/GitlabRepository.php +++ b/src/Lib/GitlabClient/Model/GitlabRepository.php @@ -22,7 +22,7 @@ public function __construct( public string $branch = 'main', ) { // Convert repository name to URL-encoded project ID for API calls - $this->projectId = \urlencode($repository); + $this->projectId = \urlencode(string: $repository); } /** @@ -40,6 +40,6 @@ public function getPath(): string */ public function getUrl(string $serverUrl = 'https://gitlab.com'): string { - return \rtrim($serverUrl, '/') . '/' . $this->repository; + return \rtrim(string: $serverUrl, characters: '/') . '/' . $this->repository; } } diff --git a/src/Lib/Html/HtmlCleaner.php b/src/Lib/Html/HtmlCleaner.php index 656bd97e..2027f315 100644 --- a/src/Lib/Html/HtmlCleaner.php +++ b/src/Lib/Html/HtmlCleaner.php @@ -14,7 +14,7 @@ public function __construct( private HtmlConverter $htmlConverter = new HtmlConverter(), ) { - $this->htmlConverter->getConfig()->setOption('strip_tags', true); + $this->htmlConverter->getConfig()->setOption(key: 'strip_tags', value: true); } public function clean(string $html): string @@ -23,6 +23,6 @@ public function clean(string $html): string return ''; } - return $this->htmlConverter->convert($html); + return $this->htmlConverter->convert(html: $html); } } diff --git a/src/Lib/Html/SelectorContentExtractor.php b/src/Lib/Html/SelectorContentExtractor.php index eb61ca8b..8dbd20fa 100644 --- a/src/Lib/Html/SelectorContentExtractor.php +++ b/src/Lib/Html/SelectorContentExtractor.php @@ -16,23 +16,23 @@ public function extract(string $html, string $selector): string } $dom = new \DOMDocument(); - \libxml_use_internal_errors(true); - $dom->loadHTML($html, LIBXML_NOWARNING | LIBXML_NOERROR); + \libxml_use_internal_errors(use_errors: true); + $dom->loadHTML(source: $html, options: LIBXML_NOWARNING | LIBXML_NOERROR); \libxml_clear_errors(); - $xpath = new \DOMXPath($dom); + $xpath = new \DOMXPath(document: $dom); // Convert CSS selector to XPath - $xpathSelector = $this->cssToXPath($selector); + $xpathSelector = $this->cssToXPath(selector: $selector); - $elements = $xpath->query($xpathSelector); + $elements = $xpath->query(expression: $xpathSelector); if ($elements === false || $elements->length === 0) { return ''; } $result = ''; foreach ($elements as $element) { - $result .= $dom->saveHTML($element) . "\n"; + $result .= $dom->saveHTML(node: $element) . "\n"; } return $result; @@ -45,13 +45,13 @@ public function extract(string $html, string $selector): string private function cssToXPath(string $selector): string { // Handle ID selector (#id) - if (\str_starts_with($selector, '#')) { - return "//*[@id='" . \substr($selector, 1) . "']"; + if (\str_starts_with(haystack: $selector, needle: '#')) { + return "//*[@id='" . \substr(string: $selector, offset: 1) . "']"; } // Handle class selector (.class) - if (\str_starts_with($selector, '.')) { - return "//*[contains(@class, '" . \substr($selector, 1) . "')]"; + if (\str_starts_with(haystack: $selector, needle: '.')) { + return "//*[contains(@class, '" . \substr(string: $selector, offset: 1) . "')]"; } // Handle element selector (div, p, etc.) diff --git a/src/Lib/HttpClient/HttpClientBootloader.php b/src/Lib/HttpClient/HttpClientBootloader.php index e3d14424..7cd48b1f 100644 --- a/src/Lib/HttpClient/HttpClientBootloader.php +++ b/src/Lib/HttpClient/HttpClientBootloader.php @@ -24,7 +24,7 @@ public function defineSingletons(): array Client $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, - ) => new Psr18Client($httpClient, $requestFactory, $streamFactory), + ) => new Psr18Client(httpClient: $httpClient, requestFactory: $requestFactory, streamFactory: $streamFactory), HttpFactory::class => HttpFactory::class, RequestFactoryInterface::class => HttpFactory::class, diff --git a/src/Lib/HttpClient/HttpResponse.php b/src/Lib/HttpClient/HttpResponse.php index 4c3928ae..96c803a2 100644 --- a/src/Lib/HttpClient/HttpResponse.php +++ b/src/Lib/HttpClient/HttpResponse.php @@ -31,9 +31,9 @@ public function getHeaders(): array public function getHeader(string $name): ?string { - $normalizedName = \strtolower($name); + $normalizedName = \strtolower(string: $name); foreach ($this->headers as $key => $value) { - if (\strtolower((string) $key) === $normalizedName) { + if (\strtolower(string: (string) $key) === $normalizedName) { return $value; } } @@ -64,11 +64,11 @@ public function isRedirect(): bool */ public function getJson(bool $assoc = true, int $depth = 512, int $options = 0): mixed { - $data = \json_decode($this->body, $assoc, $depth, $options); + $data = \json_decode(json: $this->body, associative: $assoc, depth: $depth, flags: $options); if (\json_last_error() !== JSON_ERROR_NONE) { throw new HttpException( - \sprintf( + message: \sprintf( 'Failed to parse JSON response: %s', \json_last_error_msg(), ), @@ -90,18 +90,18 @@ public function getJson(bool $assoc = true, int $depth = 512, int $options = 0): */ public function getJsonValue(string $key, mixed $default = null): mixed { - $data = $this->getJson(true); + $data = $this->getJson(); - if (!\str_contains($key, '.')) { + if (!\str_contains(haystack: $key, needle: '.')) { return $data[$key] ?? $default; } // Handle dot notation for nested values - $segments = \explode('.', $key); + $segments = \explode(separator: '.', string: $key); $current = $data; foreach ($segments as $segment) { - if (!\is_array($current) || !\array_key_exists($segment, $current)) { + if (!\is_array(value: $current) || !\array_key_exists(key: $segment, array: $current)) { return $default; } @@ -122,18 +122,18 @@ public function getJsonValue(string $key, mixed $default = null): mixed */ public function hasJsonKey(string $key): bool { - $data = $this->getJson(true); + $data = $this->getJson(); - if (!\str_contains($key, '.')) { - return \array_key_exists($key, $data); + if (!\str_contains(haystack: $key, needle: '.')) { + return \array_key_exists(key: $key, array: $data); } // Handle dot notation for nested values - $segments = \explode('.', $key); + $segments = \explode(separator: '.', string: $key); $current = $data; foreach ($segments as $segment) { - if (!\is_array($current) || !\array_key_exists($segment, $current)) { + if (!\is_array(value: $current) || !\array_key_exists(key: $segment, array: $current)) { return false; } diff --git a/src/Lib/HttpClient/Psr18Client.php b/src/Lib/HttpClient/Psr18Client.php index 38f0257e..1dcec00e 100644 --- a/src/Lib/HttpClient/Psr18Client.php +++ b/src/Lib/HttpClient/Psr18Client.php @@ -22,12 +22,12 @@ public function __construct( public function get(string $url, array $headers = []): HttpResponse { - return $this->request('GET', $url, $headers); + return $this->request(method: 'GET', url: $url, headers: $headers); } public function post(string $url, array $headers = [], ?string $body = null): HttpResponse { - return $this->request('POST', $url, $headers, $body); + return $this->request(method: 'POST', url: $url, headers: $headers, body: $body); } public function getWithRedirects(string $url, array $headers = []): HttpResponse @@ -36,13 +36,13 @@ public function getWithRedirects(string $url, array $headers = []): HttpResponse $currentUrl = $url; while (true) { - $response = $this->get($currentUrl, $headers); + $response = $this->get(url: $currentUrl, headers: $headers); if (!$response->isRedirect() || $redirectCount >= self::MAX_REDIRECTS) { return $response; } - $location = $response->getHeader('Location'); + $location = $response->getHeader(name: 'Location'); if ($location === null) { throw HttpRequestException::missingRedirectLocation(); } @@ -82,7 +82,7 @@ private function request(string $method, string $url, array $headers = [], ?stri $responseHeaders = []; foreach ($response->getHeaders() as $name => $values) { - $responseHeaders[$name] = \implode(', ', $values); + $responseHeaders[$name] = \implode(separator: ', ', array: $values); } return new HttpResponse( @@ -91,7 +91,7 @@ private function request(string $method, string $url, array $headers = [], ?stri headers: $responseHeaders, ); } catch (\Throwable $e) { - throw new HttpException(\sprintf('Failed to request URL "%s": %s', $url, $e->getMessage()), 0, $e); + throw new HttpException(message: \sprintf('Failed to request URL "%s": %s', $url, $e->getMessage()), previous: $e); } } } diff --git a/src/Lib/PathFilter/AbstractFilter.php b/src/Lib/PathFilter/AbstractFilter.php index f57862b5..cac31fb1 100644 --- a/src/Lib/PathFilter/AbstractFilter.php +++ b/src/Lib/PathFilter/AbstractFilter.php @@ -22,18 +22,18 @@ protected function matchPattern(string $value, string|array $pattern): bool return true; // No pattern means match all } - $patterns = \is_array($pattern) ? $pattern : [$pattern]; + $patterns = \is_array(value: $pattern) ? $pattern : [$pattern]; foreach ($patterns as $p) { - if (\str_contains($value, $p)) { + if (\str_contains(haystack: $value, needle: $p)) { return true; } - if (!FileHelper::isRegex($pattern)) { - $p = FileHelper::toRegex($p); + if (!FileHelper::isRegex(str: $pattern)) { + $p = FileHelper::toRegex(glob: $p); } - if ($this->matchGlob($value, $p)) { + if ($this->matchGlob(value: $value, regex: $p)) { return true; } } @@ -46,6 +46,6 @@ protected function matchPattern(string $value, string|array $pattern): bool */ protected function matchGlob(string $value, string $regex): bool { - return (bool) \preg_match($regex, $value); + return (bool) \preg_match(pattern: $regex, subject: $value); } } diff --git a/src/Lib/PathFilter/ContentsFilter.php b/src/Lib/PathFilter/ContentsFilter.php index e0451475..d778db3a 100644 --- a/src/Lib/PathFilter/ContentsFilter.php +++ b/src/Lib/PathFilter/ContentsFilter.php @@ -23,7 +23,7 @@ public function apply(array $items): array } /** @psalm-suppress InvalidArgument */ - return \array_filter($items, function (SplFileInfo $item): bool { + return \array_filter(array: $items, callback: function (SplFileInfo $item): bool { if ($item->isDir()) { return true; } @@ -33,12 +33,12 @@ public function apply(array $items): array $content = $item->getContents(); // Check "contains" patterns - if (!empty($this->contains) && !$this->contentContains($content, $this->contains)) { + if (!empty($this->contains) && !$this->contentContains(content: $content, patterns: $this->contains)) { return false; } // Check "notContains" patterns - if (!empty($this->notContains) && $this->contentContains($content, $this->notContains)) { + if (!empty($this->notContains) && $this->contentContains(content: $content, patterns: $this->notContains)) { return false; } @@ -59,16 +59,16 @@ public function apply(array $items): array */ private function contentContains(string $content, string|array $patterns): bool { - $patternArray = \is_array($patterns) ? $patterns : [$patterns]; + $patternArray = \is_array(value: $patterns) ? $patterns : [$patterns]; foreach ($patternArray as $pattern) { - if (\str_contains($content, $pattern)) { + if (\str_contains(haystack: $content, needle: $pattern)) { return true; } // Also check if it's a regex pattern - if (FileHelper::isRegex($pattern)) { - if (\preg_match($pattern, $content)) { + if (FileHelper::isRegex(str: $pattern)) { + if (\preg_match(pattern: $pattern, subject: $content)) { return true; } } diff --git a/src/Lib/PathFilter/ExcludePathFilter.php b/src/Lib/PathFilter/ExcludePathFilter.php index 5c0577f0..c1085ee3 100644 --- a/src/Lib/PathFilter/ExcludePathFilter.php +++ b/src/Lib/PathFilter/ExcludePathFilter.php @@ -24,18 +24,18 @@ public function apply(array $items): array return $items; } - return \array_filter($items, function (array $item): bool { + return \array_filter(array: $items, callback: function (array $item): bool { $path = $item['path'] ?? ''; - $filename = $item['name'] ?? \basename($path); + $filename = $item['name'] ?? \basename(path: $path); foreach ($this->excludePatterns as $pattern) { // Check against full path - if ($this->matchesPattern($path, $pattern)) { + if ($this->matchesPattern(string: $path, pattern: $pattern)) { return false; } // Also check against just the filename - if ($this->matchesPattern($filename, $pattern)) { + if ($this->matchesPattern(string: $filename, pattern: $pattern)) { return false; } } @@ -53,16 +53,16 @@ public function apply(array $items): array */ private function matchesPattern(string $string, string $pattern): bool { - if (\str_contains($string, $pattern)) { + if (\str_contains(haystack: $string, needle: $pattern)) { return true; } - if (FileHelper::isRegex($pattern)) { - return (bool) \preg_match($pattern, $string); + if (FileHelper::isRegex(str: $pattern)) { + return (bool) \preg_match(pattern: $pattern, subject: $string); } // Convert to regex if it's not already - $regex = FileHelper::toRegex($pattern); - return (bool) \preg_match($regex, $string); + $regex = FileHelper::toRegex(glob: $pattern); + return (bool) \preg_match(pattern: $regex, subject: $string); } } diff --git a/src/Lib/PathFilter/FileHelper.php b/src/Lib/PathFilter/FileHelper.php index 887a4000..66ac15fd 100644 --- a/src/Lib/PathFilter/FileHelper.php +++ b/src/Lib/PathFilter/FileHelper.php @@ -10,12 +10,12 @@ public static function isRegex(string $str): bool { $availableModifiers = 'imsxuADUn'; - if (\preg_match('/^(.{3,}?)[' . $availableModifiers . ']*$/', $str, $m)) { - $start = \substr($m[1], 0, 1); - $end = \substr($m[1], -1); + if (\preg_match(pattern: '/^(.{3,}?)[' . $availableModifiers . ']*$/', subject: $str, matches: $m)) { + $start = \substr(string: $m[1], offset: 0, length: 1); + $end = \substr(string: $m[1], offset: -1); if ($start === $end) { - return !\preg_match('/[*?[:alnum:] \\\\]/', $start); + return !\preg_match(pattern: '/[*?[:alnum:] \\\\]/', subject: $start); } foreach ([['{', '}'], ['(', ')'], ['[', ']'], ['<', '>']] as $delimiters) { @@ -38,7 +38,7 @@ public static function toRegex( $escaping = false; $inCurlies = 0; $regex = ''; - $sizeGlob = \strlen($glob); + $sizeGlob = \strlen(string: $glob); /** @psalm-suppress InvalidOperand */ for ($i = 0; $i < $sizeGlob; ++$i) { /** @psalm-suppress InvalidArrayOffset */ @@ -72,7 +72,7 @@ public static function toRegex( $i += 2 + isset($glob[$i + 3]); if ($delimiter === '/') { - $car = \str_replace('/', '\\/', $car); + $car = \str_replace(search: '/', replace: '\\/', subject: $car); } } diff --git a/src/Lib/PathFilter/FilePatternFilter.php b/src/Lib/PathFilter/FilePatternFilter.php index f3a6b6ae..098bbcf8 100644 --- a/src/Lib/PathFilter/FilePatternFilter.php +++ b/src/Lib/PathFilter/FilePatternFilter.php @@ -24,14 +24,14 @@ public function apply(array $items): array return $items; } - return \array_filter($items, function (array $item): bool { + return \array_filter(array: $items, callback: function (array $item): bool { // Skip directories if ($item['type'] === 'dir') { return true; } $filename = $item['name']; - return $this->matchPattern($filename, $this->pattern); + return $this->matchPattern(value: $filename, pattern: $this->pattern); }); } } diff --git a/src/Lib/PathFilter/PathFilter.php b/src/Lib/PathFilter/PathFilter.php index d65902cb..cca4254c 100644 --- a/src/Lib/PathFilter/PathFilter.php +++ b/src/Lib/PathFilter/PathFilter.php @@ -24,9 +24,9 @@ public function apply(array $items): array return $items; } - return \array_filter($items, function (array $item): bool { + return \array_filter(array: $items, callback: function (array $item): bool { $path = $item['path'] ?? ''; - return $this->matchPattern($path, $this->pathPattern); + return $this->matchPattern(value: $path, pattern: $this->pathPattern); }); } } diff --git a/src/Lib/TokenCounter/CharTokenCounter.php b/src/Lib/TokenCounter/CharTokenCounter.php index 1b1a15b8..26a465e5 100644 --- a/src/Lib/TokenCounter/CharTokenCounter.php +++ b/src/Lib/TokenCounter/CharTokenCounter.php @@ -8,17 +8,17 @@ { public function countFile(string $filePath): int { - if (\is_dir($filePath)) { + if (\is_dir(filename: $filePath)) { return 0; } - if (!\file_exists($filePath) || !\is_readable($filePath)) { + if (!\file_exists(filename: $filePath) || !\is_readable(filename: $filePath)) { return 0; } - $content = \file_get_contents($filePath); + $content = \file_get_contents(filename: $filePath); - return $content === false ? 0 : \mb_strlen($content); + return $content === false ? 0 : \mb_strlen(string: $content); } public function calculateDirectoryCount(array $directory): int @@ -26,10 +26,10 @@ public function calculateDirectoryCount(array $directory): int $totalChars = 0; foreach ($directory as $children) { - if (\is_array($children)) { - $totalChars += $this->calculateDirectoryCount($children); + if (\is_array(value: $children)) { + $totalChars += $this->calculateDirectoryCount(directory: $children); } else { - $totalChars += $this->countFile($children); + $totalChars += $this->countFile(filePath: $children); } } diff --git a/src/Lib/TreeBuilder/DirectorySorter.php b/src/Lib/TreeBuilder/DirectorySorter.php index 68812d39..4966fc8c 100644 --- a/src/Lib/TreeBuilder/DirectorySorter.php +++ b/src/Lib/TreeBuilder/DirectorySorter.php @@ -20,41 +20,41 @@ public static function sort(iterable $directories): array { // First, remove any duplicates and ensure consistent path separators $normalized = \array_map( - static fn(string $path): string => self::normalizePath($path), - \array_unique((array) $directories), + callback: static fn(string $path): string => self::normalizePath($path), + array: \array_unique(array: (array) $directories), ); // Early return for empty arrays or single item arrays (already sorted) - if (\count($normalized) <= 1) { + if (\count(value: $normalized) <= 1) { return $normalized; } // First sort alphabetically to ensure consistent ordering - \sort($normalized); + \sort(array: $normalized); // Then re-sort to ensure parent directories appear before their children - \usort($normalized, static function (string $a, string $b): int { + \usort(array: $normalized, callback: static function (string $a, string $b): int { // If one path is a direct parent of another, make sure the parent comes first - if (\str_starts_with($b, $a . '/')) { + if (\str_starts_with(haystack: $b, needle: $a . '/')) { return -1; } - if (\str_starts_with($a, $b . '/')) { + if (\str_starts_with(haystack: $a, needle: $b . '/')) { return 1; } // Get the top-level directories for comparison - $topDirA = \explode('/', $a)[0]; - $topDirB = \explode('/', $b)[0]; + $topDirA = \explode(separator: '/', string: $a)[0]; + $topDirB = \explode(separator: '/', string: $b)[0]; // If top-level directories are different, sort alphabetically if ($topDirA !== $topDirB) { - return \strcmp($topDirA, $topDirB); + return \strcmp(string1: $topDirA, string2: $topDirB); } // Count path segments (depth) - $depthA = \substr_count($a, '/'); - $depthB = \substr_count($b, '/'); + $depthA = \substr_count(haystack: $a, needle: '/'); + $depthB = \substr_count(haystack: $b, needle: '/'); // Sort by depth for paths with the same parent if ($depthA !== $depthB) { @@ -62,10 +62,10 @@ public static function sort(iterable $directories): array } // If same depth and not parent-child, sort alphabetically - return \strcmp($a, $b); + return \strcmp(string1: $a, string2: $b); }); - return \array_unique($normalized); + return \array_unique(array: $normalized); } /** @@ -102,8 +102,8 @@ public static function sortPreservingSeparators(array $directories): array // Map back to original paths return \array_map( - static fn(string $normalizedPath): string => $mapping[$normalizedPath], - $sorted, + callback: static fn(string $normalizedPath): string => $mapping[$normalizedPath], + array: $sorted, ); } @@ -119,14 +119,14 @@ public static function sortPreservingSeparators(array $directories): array private static function normalizePath(string $path): string { // Replace Windows backslashes with forward slashes - $path = \str_replace('\\', '/', $path); + $path = \str_replace(search: '\\', replace: '/', subject: $path); // Remove trailing slashes - $path = \rtrim($path, '/'); + $path = \rtrim(string: $path, characters: '/'); // Normalize Windows drive letter format (if present) - if (\preg_match('/^[A-Z]:\//i', $path)) { - $path = \substr($path, 2); // Remove drive letter and colon (e.g., "C:") + if (\preg_match(pattern: '/^[A-Z]:\//i', subject: $path)) { + $path = \substr(string: $path, offset: 2); // Remove drive letter and colon (e.g., "C:") } return $path; diff --git a/src/Lib/TreeBuilder/FileTreeBuilder.php b/src/Lib/TreeBuilder/FileTreeBuilder.php index 7705a477..896f87c4 100644 --- a/src/Lib/TreeBuilder/FileTreeBuilder.php +++ b/src/Lib/TreeBuilder/FileTreeBuilder.php @@ -28,7 +28,7 @@ public function buildTree( string $basePath, array $options = [], ): string { - $files = DirectorySorter::sortPreservingSeparators($files); + $files = DirectorySorter::sortPreservingSeparators(directories: $files); // Get or create a renderer @@ -38,19 +38,19 @@ public function buildTree( $normalizedFiles = []; foreach ($files as $file) { // Normalize both file and base path consistently across all platforms - $normalizedFile = $this->normalizePath($file); - $normalizedBasePath = $this->normalizePath($basePath); + $normalizedFile = $this->normalizePath(path: $file); + $normalizedBasePath = $this->normalizePath(path: $basePath); // Remove base path from file path to get the relative path - $normalizedPath = \trim(\str_replace($normalizedBasePath, '', $normalizedFile)); + $normalizedPath = \trim(string: \str_replace(search: $normalizedBasePath, replace: '', subject: $normalizedFile)); // Additional cleaning (Windows can produce paths with mixed separators) - if (!\str_starts_with($normalizedPath, '/')) { + if (!\str_starts_with(haystack: $normalizedPath, needle: '/')) { $normalizedPath = '/' . $normalizedPath; } - $ext = \pathinfo($normalizedPath, PATHINFO_EXTENSION); - $isDirectory = \is_dir($file) || $ext === ''; + $ext = \pathinfo(path: $normalizedPath, flags: PATHINFO_EXTENSION); + $isDirectory = \is_dir(filename: $file) || $ext === ''; $normalizedFiles[] = [ 'path' => $normalizedPath, @@ -61,18 +61,18 @@ public function buildTree( // Sort files for consistent display - \usort($normalizedFiles, static fn($a, $b) => $a['path'] <=> $b['path']); + \usort(array: $normalizedFiles, callback: static fn($a, $b) => $a['path'] <=> $b['path']); // Build tree structure with all files and directories $tree = []; foreach ($normalizedFiles as $fileInfo) { - $parts = \array_filter(\explode('/', \trim($fileInfo['path'], '/')), strlen(...)); + $parts = \array_filter(array: \explode(separator: '/', string: \trim(string: $fileInfo['path'], characters: '/')), callback: strlen(...)); $this->addToTree( - $tree, - $parts, - $fileInfo['fullPath'], - $fileInfo['isDirectory'], + tree: $tree, + parts: $parts, + fullPath: $fileInfo['fullPath'], + isDirectoryPath: $fileInfo['isDirectory'], ); } @@ -98,7 +98,7 @@ private function addToTree(array &$tree, array $parts, string $fullPath = '', bo // Determine if it's a directory: // - Either it's not the last segment of the path // - Or the entire path represents a directory - $isDirectory = $index < \count($parts) - 1 || $isDirectoryPath; + $isDirectory = $index < \count(value: $parts) - 1 || $isDirectoryPath; // For directories, create an array for children // For files, store the full path for metadata access @@ -106,7 +106,7 @@ private function addToTree(array &$tree, array $parts, string $fullPath = '', bo } // Only continue traversing if this is a directory (array) - if (\is_array($_current[$part])) { + if (\is_array(value: $_current[$part])) { $_current = &$_current[$part]; } } @@ -123,11 +123,11 @@ private function addToTree(array &$tree, array $parts, string $fullPath = '', bo private function normalizePath(string $path): string { // Replace Windows backslashes with forward slashes - $path = \str_replace('\\', '/', $path); + $path = \str_replace(search: '\\', replace: '/', subject: $path); // Normalize Windows drive letter format (if present) - if (\preg_match('/^[A-Z]:\//i', $path)) { - $path = \substr($path, 2); // Remove drive letter and colon (e.g., "C:") + if (\preg_match(pattern: '/^[A-Z]:\//i', subject: $path)) { + $path = \substr(string: $path, offset: 2); // Remove drive letter and colon (e.g., "C:") } return $path; diff --git a/src/Lib/TreeBuilder/TreeRenderer/AsciiTreeRenderer.php b/src/Lib/TreeBuilder/TreeRenderer/AsciiTreeRenderer.php index e859dbde..3179c7d0 100644 --- a/src/Lib/TreeBuilder/TreeRenderer/AsciiTreeRenderer.php +++ b/src/Lib/TreeBuilder/TreeRenderer/AsciiTreeRenderer.php @@ -53,13 +53,13 @@ private function renderNode( } $result = ''; - $count = \count($node); + $count = \count(value: $node); $i = 0; foreach ($node as $name => $children) { $i++; $isLastItem = ($i === $count); - $isDirectory = \is_array($children); + $isDirectory = \is_array(value: $children); // Skip files if includeFiles is false if (!$isDirectory && !$includeFiles) { @@ -79,31 +79,31 @@ private function renderNode( if ($showSize || $showLastModified || $showCharCount) { if ($showSize) { $size = $isDirectory - ? $this->calculateDirectorySize($children) - : (\file_exists($fullPath) ? \filesize($fullPath) : 0); - $metadata .= $this->formatSize($size); + ? $this->calculateDirectorySize(directory: $children) + : (\file_exists(filename: $fullPath) ? \filesize(filename: $fullPath) : 0); + $metadata .= $this->formatSize(bytes: $size); } if ($showLastModified) { $mtime = $isDirectory - ? $this->getLatestModificationTime($children) - : (\file_exists($fullPath) ? \filemtime($fullPath) : 0); + ? $this->getLatestModificationTime(directory: $children) + : (\file_exists(filename: $fullPath) ? \filemtime(filename: $fullPath) : 0); if ($showSize) { $metadata .= ', '; } - $metadata .= \date('Y-m-d', $mtime ?: \time()); + $metadata .= \date(format: 'Y-m-d', timestamp: $mtime ?: \time()); } // Add character count if requested if ($showCharCount) { $charCount = $isDirectory ? $this->tokenCounter->calculateDirectoryCount($children) - : (\file_exists($fullPath) ? $this->tokenCounter->countFile($fullPath) : 0); + : (\file_exists(filename: $fullPath) ? $this->tokenCounter->countFile($fullPath) : 0); if ($showSize || $showLastModified) { $metadata .= ', '; } if ($charCount > 0) { - $metadata .= \number_format($charCount) . ' chars'; + $metadata .= \number_format(num: $charCount) . ' chars'; } } } @@ -127,15 +127,15 @@ private function renderNode( if ($isDirectory) { $newPrefix = $prefix . ($isLast ? ' ' : '│ '); $result .= $this->renderNode( - $children, - $newPrefix, - $isLastItem, - $showSize, - $showLastModified, - $showCharCount, - $includeFiles, - $dirContext, - $relativePath, // Pass the updated relative path + node: $children, + prefix: $newPrefix, + isLast: $isLastItem, + showSize: $showSize, + showLastModified: $showLastModified, + showCharCount: $showCharCount, + includeFiles: $includeFiles, + dirContext: $dirContext, + currentPath: $relativePath, // Pass the updated relative path ); } } @@ -154,10 +154,10 @@ private function calculateDirectorySize(array $directory): int $totalSize = 0; foreach ($directory as $children) { - if (\is_array($children)) { - $totalSize += $this->calculateDirectorySize($children); + if (\is_array(value: $children)) { + $totalSize += $this->calculateDirectorySize(directory: $children); } else { - $totalSize += \file_exists($children) ? \filesize($children) : 0; + $totalSize += \file_exists(filename: $children) ? \filesize(filename: $children) : 0; } } @@ -175,9 +175,9 @@ private function getLatestModificationTime(array $directory): int $latestTime = 0; foreach ($directory as $children) { - $time = \is_array($children) - ? $this->getLatestModificationTime($children) - : (\file_exists($children) ? (int) \filemtime($children) : 0); + $time = \is_array(value: $children) + ? $this->getLatestModificationTime(directory: $children) + : (\file_exists(filename: $children) ? (int) \filemtime(filename: $children) : 0); if ($time > $latestTime) { $latestTime = $time; @@ -201,8 +201,8 @@ private function formatSize(int $bytes): string /** * @psalm-suppress InvalidOperand */ - $pow = \floor(($bytes ? \log($bytes) : 0) / \log(1024)); - $pow = \min($pow, \count($units) - 1); + $pow = \floor(num: ($bytes ? \log(num: $bytes) : 0) / \log(num: 1024)); + $pow = \min($pow, \count(value: $units) - 1); /** * @psalm-suppress InvalidOperand diff --git a/src/Lib/TreeBuilder/TreeViewConfig.php b/src/Lib/TreeBuilder/TreeViewConfig.php index 72a8ad07..2ea623d1 100644 --- a/src/Lib/TreeBuilder/TreeViewConfig.php +++ b/src/Lib/TreeBuilder/TreeViewConfig.php @@ -39,13 +39,13 @@ public static function fromArray(array $data): self } // Handle boolean case (backward compatibility) - if (isset($data['treeView']) && \is_bool($data['treeView'])) { + if (isset($data['treeView']) && \is_bool(value: $data['treeView'])) { return new self(enabled: $data['treeView']); } // Handle object/array case $config = $data['treeView'] ?? []; - if (!\is_array($config)) { + if (!\is_array(value: $config)) { return new self(enabled: (bool) $config); } @@ -80,7 +80,7 @@ public function getOptions(): array */ public function jsonSerialize(): array { - return \array_filter([ + return \array_filter(array: [ 'enabled' => $this->enabled, 'showSize' => $this->showSize, 'showLastModified' => $this->showLastModified, @@ -88,6 +88,6 @@ public function jsonSerialize(): array 'includeFiles' => $this->includeFiles === false ? false : null, 'maxDepth' => $this->maxDepth > 0 ? $this->maxDepth : null, 'dirContext' => !empty($this->dirContext) ? $this->dirContext : null, - ], static fn($value) => $value !== null); + ], callback: static fn($value) => $value !== null); } } diff --git a/src/Lib/Variable/CompositeProcessor.php b/src/Lib/Variable/CompositeProcessor.php index 7f0d8b91..755cd4fe 100644 --- a/src/Lib/Variable/CompositeProcessor.php +++ b/src/Lib/Variable/CompositeProcessor.php @@ -16,7 +16,7 @@ public function __construct( public function process(string $text): string { foreach ($this->processors as $processor) { - $text = $processor->process($text); + $text = $processor->process(text: $text); } return $text; diff --git a/src/Lib/Variable/Provider/CompositeVariableProvider.php b/src/Lib/Variable/Provider/CompositeVariableProvider.php index a1e3074a..80ec1538 100644 --- a/src/Lib/Variable/Provider/CompositeVariableProvider.php +++ b/src/Lib/Variable/Provider/CompositeVariableProvider.php @@ -21,7 +21,7 @@ public function __construct( VariableProviderInterface ...$providers, ) { foreach ($providers as $provider) { - $this->addProvider($provider); + $this->addProvider(provider: $provider); } } diff --git a/src/Lib/Variable/Provider/ConfigVariableProvider.php b/src/Lib/Variable/Provider/ConfigVariableProvider.php index 53e84879..99023860 100644 --- a/src/Lib/Variable/Provider/ConfigVariableProvider.php +++ b/src/Lib/Variable/Provider/ConfigVariableProvider.php @@ -19,7 +19,7 @@ final class ConfigVariableProvider implements VariableProviderInterface public function __construct(array $variables = []) { - $this->setVariables($variables); + $this->setVariables(variables: $variables); } /** @@ -34,7 +34,7 @@ public function setVariables(array $variables): self // Convert all values to strings foreach ($variables as $key => $value) { // Skip non-scalar values - if (!\is_scalar($value)) { + if (!\is_scalar(value: $value)) { continue; } @@ -46,7 +46,7 @@ public function setVariables(array $variables): self public function has(string $name): bool { - return \array_key_exists($name, $this->variables); + return \array_key_exists(key: $name, array: $this->variables); } public function get(string $name): ?string diff --git a/src/Lib/Variable/Provider/DotEnvVariableProvider.php b/src/Lib/Variable/Provider/DotEnvVariableProvider.php index 63dc040e..dd54c979 100644 --- a/src/Lib/Variable/Provider/DotEnvVariableProvider.php +++ b/src/Lib/Variable/Provider/DotEnvVariableProvider.php @@ -17,7 +17,7 @@ public function __construct( private ?string $envFileName = null, ) { if ($this->rootPath) { - $dotenv = Dotenv::create($repository, $this->rootPath, $this->envFileName); + $dotenv = Dotenv::create(repository: $repository, paths: $this->rootPath, names: $this->envFileName); $dotenv->load(); } diff --git a/src/Lib/Variable/Provider/PredefinedVariableProvider.php b/src/Lib/Variable/Provider/PredefinedVariableProvider.php index 89f1110a..c928a8e5 100644 --- a/src/Lib/Variable/Provider/PredefinedVariableProvider.php +++ b/src/Lib/Variable/Provider/PredefinedVariableProvider.php @@ -11,7 +11,7 @@ { public function has(string $name): bool { - return \array_key_exists($name, $this->getPredefinedVariables()); + return \array_key_exists(key: $name, array: $this->getPredefinedVariables()); } public function get(string $name): ?string @@ -27,9 +27,9 @@ public function get(string $name): ?string private function getPredefinedVariables(): array { return [ - 'DATETIME' => \date('Y-m-d H:i:s'), - 'DATE' => \date('Y-m-d'), - 'TIME' => \date('H:i:s'), + 'DATETIME' => \date(format: 'Y-m-d H:i:s'), + 'DATE' => \date(format: 'Y-m-d'), + 'TIME' => \date(format: 'H:i:s'), 'TIMESTAMP' => (string) \time(), 'USER' => \get_current_user(), 'HOME_DIR' => \getenv('HOME') ?: (\getenv('USERPROFILE') ?: '/'), diff --git a/src/Lib/Variable/VariableBootloader.php b/src/Lib/Variable/VariableBootloader.php index 2e7bf429..8974cf37 100644 --- a/src/Lib/Variable/VariableBootloader.php +++ b/src/Lib/Variable/VariableBootloader.php @@ -55,7 +55,7 @@ public function defineSingletons(): array VariableReplacementProcessorInterface::class => static fn( VariableReplacementProcessor $replacementProcessor, - ) => new CompositeProcessor([ + ) => new CompositeProcessor(processors: [ $replacementProcessor, ]), @@ -68,6 +68,6 @@ public function boot( VariablesParserPlugin $variablesParserPlugin, ): void { // Register the variables parser plugin with the config loader - $configLoaderBootloader->registerParserPlugin($variablesParserPlugin); + $configLoaderBootloader->registerParserPlugin(plugin: $variablesParserPlugin); } } diff --git a/src/Lib/Variable/VariableReplacementProcessor.php b/src/Lib/Variable/VariableReplacementProcessor.php index 9ae44144..3701638a 100644 --- a/src/Lib/Variable/VariableReplacementProcessor.php +++ b/src/Lib/Variable/VariableReplacementProcessor.php @@ -30,16 +30,16 @@ public function process(string $text): string { // Replace ${VAR_NAME} syntax $result = \preg_replace_callback( - '/\${([a-zA-Z0-9_]+)}/', - fn(array $matches) => $this->replaceVariable($matches[1], '${%s}'), - $text, + pattern: '/\${([a-zA-Z0-9_]+)}/', + callback: fn(array $matches) => $this->replaceVariable(name: $matches[1], format: '${%s}'), + subject: $text, ); // Replace {{VAR_NAME}} syntax return (string) \preg_replace_callback( - '/{{([a-zA-Z0-9_]+)}}/', - fn(array $matches) => $this->replaceVariable($matches[1], '{{%s}}'), - (string) $result, + pattern: '/{{([a-zA-Z0-9_]+)}}/', + callback: fn(array $matches) => $this->replaceVariable(name: $matches[1], format: '{{%s}}'), + subject: (string) $result, ); } diff --git a/src/Lib/Variable/VariableResolver.php b/src/Lib/Variable/VariableResolver.php index 897d7a46..abc76e09 100644 --- a/src/Lib/Variable/VariableResolver.php +++ b/src/Lib/Variable/VariableResolver.php @@ -15,7 +15,7 @@ public function __construct( public function with(VariableReplacementProcessorInterface $processor): self { - return new self(new CompositeProcessor([ + return new self(new CompositeProcessor(processors: [ $this->processor, $processor, ])); @@ -30,8 +30,8 @@ public function resolve(string|array|null $strings): string|array|null return null; } - if (\is_array($strings)) { - return \array_map($this->resolve(...), $strings); + if (\is_array(value: $strings)) { + return \array_map(callback: $this->resolve(...), array: $strings); } return $this->processor->process($strings); diff --git a/src/McpServer/Action/Prompts/FilesystemOperationsAction.php b/src/McpServer/Action/Prompts/FilesystemOperationsAction.php index 4a2be043..ace3344d 100644 --- a/src/McpServer/Action/Prompts/FilesystemOperationsAction.php +++ b/src/McpServer/Action/Prompts/FilesystemOperationsAction.php @@ -42,7 +42,7 @@ public function __invoke(ServerRequestInterface $request): GetPromptResult new PromptMessage( role: Role::User, content: new TextContent( - text: \implode("\n", $rules), + text: \implode(separator: "\n", array: $rules), ), ), ], diff --git a/src/McpServer/Action/Prompts/ListPromptsAction.php b/src/McpServer/Action/Prompts/ListPromptsAction.php index 321110ea..07e27a2a 100644 --- a/src/McpServer/Action/Prompts/ListPromptsAction.php +++ b/src/McpServer/Action/Prompts/ListPromptsAction.php @@ -38,6 +38,6 @@ public function __invoke(ServerRequestInterface $request): ListPromptsResult $prompts[] = $prompt->prompt; } - return new ListPromptsResult($prompts); + return new ListPromptsResult(prompts: $prompts); } } diff --git a/src/McpServer/Action/Resources/GenerateConfigAction.php b/src/McpServer/Action/Resources/GenerateConfigAction.php index b3eeefc7..03094144 100644 --- a/src/McpServer/Action/Resources/GenerateConfigAction.php +++ b/src/McpServer/Action/Resources/GenerateConfigAction.php @@ -33,54 +33,54 @@ public function __construct( public function __invoke(ServerRequestInterface $request): ReadResourceResult { try { - $detection = $this->detectionService->detectBestTemplate($this->dirs->getRootPath())->jsonSerialize(); + $detection = $this->detectionService->detectBestTemplate(projectRoot: $this->dirs->getRootPath())->jsonSerialize(); $response = <<<'INSTRUCTIONS' You are an expert system for analyzing software projects and generating CTX configuration files. - + ## Your Role - Analyze the provided project structure, user requirements, and generate a complete, valid CTX + Analyze the provided project structure, user requirements, and generate a complete, valid CTX configuration file that follows the JSON Schema specification. - + ## JSON Schema %s - + ## Project info %s - + ## Available Tools 1. Use directory-list if you need to list directories in the project 2. Use file-read if you need to read files in the project - + ## Analysis Process 1. **Project Structure**: Examine directories, files, and detected frameworks 2. **Framework Patterns**: Apply framework-specific best practices 3. **Context Prioritization**: Focus on code most valuable for AI development assistance 4. **Document Organization**: Create logical, coherent context document groupings - + ## Configuration Rules 1. **Schema Compliance**: All output must validate against the provided JSON Schema 2. **Practical Focus**: Prioritize directories and files developers actively work with 3. **Logical Grouping**: Create documents that group related functionality 4. **Appropriate Sources**: Use optimal source types (file/tree) for each context need 5. **Meaningful Descriptions**: Provide clear, descriptive document names - + ## Output Requirements - Generate complete YAML configuration in artefact form - Use tree sources for structure overview - Use file sources for code analysis - Include tags - - Do not include modifiers, + - Do not include modifiers, - Validate all paths exist in project structure INSTRUCTIONS; $response = \sprintf( $response, - \json_encode($this->jsonSchema->getSimplifiedSchema()), - \json_encode($detection), + \json_encode(value: $this->jsonSchema->getSimplifiedSchema()), + \json_encode(value: $detection), ); - return new ReadResourceResult([ + return new ReadResourceResult(contents: [ new TextResourceContents( uri: 'ctx://schema-builder-instructions', mimeType: 'application/json', @@ -94,7 +94,7 @@ public function __invoke(ServerRequestInterface $request): ReadResourceResult 'trace' => $e->getTraceAsString(), ]); - return new ReadResourceResult([ + return new ReadResourceResult(contents: [ new TextResourceContents( uri: 'ctx://schema-builder-instructions', mimeType: 'application/json', diff --git a/src/McpServer/Action/Resources/GetDocumentContentResourceAction.php b/src/McpServer/Action/Resources/GetDocumentContentResourceAction.php index 5cceb8cd..30088c29 100644 --- a/src/McpServer/Action/Resources/GetDocumentContentResourceAction.php +++ b/src/McpServer/Action/Resources/GetDocumentContentResourceAction.php @@ -30,7 +30,7 @@ public function __invoke(ServerRequestInterface $request): ReadResourceResult $path = $request->getAttribute('path'); $this->logger->info('Getting document content', ['path' => $path]); - $config = new ConfigRegistryAccessor($this->configLoader->load()); + $config = new ConfigRegistryAccessor(registry: $this->configLoader->load()); $contents = []; foreach ($config->getDocuments() as $document) { @@ -38,13 +38,13 @@ public function __invoke(ServerRequestInterface $request): ReadResourceResult $contents[] = new TextResourceContents( uri: 'ctx://document/' . $document->outputPath, mimeType: 'text/markdown', - text: (string) $this->compiler->buildContent(new ErrorCollection(), $document)->content, + text: (string) $this->compiler->buildContent(errors: new ErrorCollection(), document: $document)->content, ); break; } } - return new ReadResourceResult($contents); + return new ReadResourceResult(contents: $contents); } } diff --git a/src/McpServer/Action/Resources/JsonSchemaResourceAction.php b/src/McpServer/Action/Resources/JsonSchemaResourceAction.php index fd220318..1a89dfa2 100644 --- a/src/McpServer/Action/Resources/JsonSchemaResourceAction.php +++ b/src/McpServer/Action/Resources/JsonSchemaResourceAction.php @@ -32,11 +32,11 @@ public function __invoke(ServerRequestInterface $request): ReadResourceResult { $this->logger->info('Getting JSON schema'); - return new ReadResourceResult([ + return new ReadResourceResult(contents: [ new TextResourceContents( uri: 'ctx://json-schema', mimeType: 'application/json', - text: \json_encode($this->jsonSchema->getSimplifiedSchema()), + text: \json_encode(value: $this->jsonSchema->getSimplifiedSchema()), ), ]); } diff --git a/src/McpServer/Action/Resources/ListResourcesAction.php b/src/McpServer/Action/Resources/ListResourcesAction.php index 1c01849f..393a5213 100644 --- a/src/McpServer/Action/Resources/ListResourcesAction.php +++ b/src/McpServer/Action/Resources/ListResourcesAction.php @@ -38,10 +38,10 @@ public function __invoke(ServerRequestInterface $request): ListResourcesResult } // Add document resources from config loader - $config = new ConfigRegistryAccessor($this->configLoader->load()); + $config = new ConfigRegistryAccessor(registry: $this->configLoader->load()); foreach ($config->getDocuments() as $document) { - $tags = \implode(', ', $document->getTags()); + $tags = \implode(separator: ', ', array: $document->getTags()); $resources[] = new Resource( uri: 'ctx://document/' . $document->outputPath, diff --git a/src/McpServer/Action/Tools/Context/ContextAction.php b/src/McpServer/Action/Tools/Context/ContextAction.php index 0871a410..5ee45ec9 100644 --- a/src/McpServer/Action/Tools/Context/ContextAction.php +++ b/src/McpServer/Action/Tools/Context/ContextAction.php @@ -32,24 +32,24 @@ public function __invoke(ServerRequestInterface $request): CallToolResult $this->logger->info('Processing context tool'); try { - $config = new ConfigRegistryAccessor($this->configLoader->load()); + $config = new ConfigRegistryAccessor(registry: $this->configLoader->load()); $content = []; foreach ($config->getDocuments() as $document) { $content[] = new TextContent( - text: \json_encode($document->jsonSerialize()), + text: \json_encode(value: $document->jsonSerialize()), ); } // Return all documents in JSON format - return new CallToolResult($content); + return new CallToolResult(content: $content); } catch (\Throwable $e) { $this->logger->error('Error listing contexts', [ 'error' => $e->getMessage(), ]); // Return all documents in JSON format - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } } diff --git a/src/McpServer/Action/Tools/Context/ContextGetAction.php b/src/McpServer/Action/Tools/Context/ContextGetAction.php index c7ea31e7..78141423 100644 --- a/src/McpServer/Action/Tools/Context/ContextGetAction.php +++ b/src/McpServer/Action/Tools/Context/ContextGetAction.php @@ -39,23 +39,23 @@ public function __invoke(ContextGetRequest $request): CallToolResult $path = $request->path; if (empty($path)) { - return ToolResult::error('Missing path parameter'); + return ToolResult::error(error: 'Missing path parameter'); } try { - $config = new ConfigRegistryAccessor($this->configLoader->load()); + $config = new ConfigRegistryAccessor(registry: $this->configLoader->load()); foreach ($config->getDocuments() as $document) { if ($document->outputPath === $path) { - $content = (string) $this->documentCompiler->buildContent(new ErrorCollection(), $document)->content; + $content = (string) $this->documentCompiler->buildContent(errors: new ErrorCollection(), document: $document)->content; // Return all documents in JSON format - return ToolResult::text($content); + return ToolResult::text(text: $content); } } // Return all documents in JSON format - return ToolResult::error(\sprintf("Document with path '%s' not found", $path)); + return ToolResult::error(error: \sprintf("Document with path '%s' not found", $path)); } catch (\Throwable $e) { $this->logger->error('Error getting context', [ 'path' => $path, @@ -63,7 +63,7 @@ public function __invoke(ContextGetRequest $request): CallToolResult ]); // Return all documents in JSON format - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } } diff --git a/src/McpServer/Action/Tools/Context/ContextRequestAction.php b/src/McpServer/Action/Tools/Context/ContextRequestAction.php index 34e6f732..f7734b16 100644 --- a/src/McpServer/Action/Tools/Context/ContextRequestAction.php +++ b/src/McpServer/Action/Tools/Context/ContextRequestAction.php @@ -40,28 +40,28 @@ public function __invoke(ContextRequestRequest $request): CallToolResult $json = $request->json; if (empty($json)) { - return ToolResult::error('Missing JSON parameter'); + return ToolResult::error(error: 'Missing JSON parameter'); } try { - $loader = $this->provider->fromString($json); - $config = new ConfigRegistryAccessor($loader->load()); + $loader = $this->provider->fromString(jsonConfig: $json); + $config = new ConfigRegistryAccessor(registry: $loader->load()); $compiledDocuments = []; foreach ($config->getDocuments() as $document) { $compiledDocuments[] = new TextContent( - text: (string) $this->documentCompiler->buildContent(new ErrorCollection(), $document)->content, + text: (string) $this->documentCompiler->buildContent(errors: new ErrorCollection(), document: $document)->content, ); } - return new CallToolResult($compiledDocuments); + return new CallToolResult(content: $compiledDocuments); } catch (\Throwable $e) { $this->logger->error('Error processing context request', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } } diff --git a/src/McpServer/Action/Tools/Docs/FetchLibraryDocsAction.php b/src/McpServer/Action/Tools/Docs/FetchLibraryDocsAction.php index 23d0c4de..9c7a1d14 100644 --- a/src/McpServer/Action/Tools/Docs/FetchLibraryDocsAction.php +++ b/src/McpServer/Action/Tools/Docs/FetchLibraryDocsAction.php @@ -33,12 +33,12 @@ public function __invoke(FetchLibraryDocsRequest $request): CallToolResult $this->logger->info('Processing find-docs tool'); // Get params from the parsed body for POST requests - $libraryId = \trim($request->id); + $libraryId = \trim(string: $request->id); $tokens = $request->tokens; - $topic = $request->topic !== null ? \trim($request->topic) : null; + $topic = $request->topic !== null ? \trim(string: $request->topic) : null; if (empty($libraryId)) { - return ToolResult::error('Missing id parameter'); + return ToolResult::error(error: 'Missing id parameter'); } try { @@ -48,9 +48,9 @@ public function __invoke(FetchLibraryDocsRequest $request): CallToolResult topic: $topic, ); - return ToolResult::text($documentation); + return ToolResult::text(text: $documentation); } catch (Context7ClientException $e) { - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } catch (\Throwable $e) { $this->logger->error('Unexpected error in fetch-library-docs tool', [ 'libraryId' => $libraryId, @@ -58,7 +58,7 @@ public function __invoke(FetchLibraryDocsRequest $request): CallToolResult 'trace' => $e->getTraceAsString(), ]); - return ToolResult::error('Error fetching library documentation. Please try again later. ' . $e->getMessage()); + return ToolResult::error(error: 'Error fetching library documentation. Please try again later. ' . $e->getMessage()); } } } diff --git a/src/McpServer/Action/Tools/Docs/LibrarySearchAction.php b/src/McpServer/Action/Tools/Docs/LibrarySearchAction.php index 581ccbc2..4a1bc39d 100644 --- a/src/McpServer/Action/Tools/Docs/LibrarySearchAction.php +++ b/src/McpServer/Action/Tools/Docs/LibrarySearchAction.php @@ -33,11 +33,11 @@ public function __invoke(LibrarySearchRequest $request): CallToolResult $this->logger->info('Processing library-search tool'); // Get params from the parsed body for POST requests - $query = \trim($request->query); + $query = \trim(string: $request->query); $maxResults = \min(10, \max(1, $request->maxResults ?? 5)); if (empty($query)) { - return ToolResult::error('Missing query parameter'); + return ToolResult::error(error: 'Missing query parameter'); } try { @@ -46,9 +46,9 @@ public function __invoke(LibrarySearchRequest $request): CallToolResult maxResults: $maxResults, ); - return ToolResult::success($searchResult); + return ToolResult::success(data: $searchResult); } catch (Context7ClientException $e) { - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } catch (\Throwable $e) { $this->logger->error('Unexpected error in library-search tool', [ 'query' => $query, @@ -56,7 +56,7 @@ public function __invoke(LibrarySearchRequest $request): CallToolResult 'trace' => $e->getTraceAsString(), ]); - return ToolResult::error('Error searching libraries: ' . $e->getMessage()); + return ToolResult::error(error: 'Error searching libraries: ' . $e->getMessage()); } } } diff --git a/src/McpServer/Action/Tools/ExecuteCustomToolAction.php b/src/McpServer/Action/Tools/ExecuteCustomToolAction.php index 3b96e895..2f9df7ce 100644 --- a/src/McpServer/Action/Tools/ExecuteCustomToolAction.php +++ b/src/McpServer/Action/Tools/ExecuteCustomToolAction.php @@ -30,7 +30,7 @@ public function __invoke(ServerRequestInterface $request): CallToolResult // Get params from the parsed body for POST requests $parsedBody = (array) $request->getParsedBody(); - if (empty($toolId) || !\is_string($toolId)) { + if (empty($toolId) || !\is_string(value: $toolId)) { $this->logger->warning('No tool ID provided'); return new CallToolResult( content: [new TextContent(text: 'No tool ID provided')], @@ -52,7 +52,7 @@ public function __invoke(ServerRequestInterface $request): CallToolResult $tool = $this->toolProvider->get($toolId); // Execute the tool - $result = $this->toolHandler->createHandlerForTool($tool)->execute($tool, $parsedBody); + $result = $this->toolHandler->createHandlerForTool(tool: $tool)->execute($tool, $parsedBody); // Format the result $output = \sprintf( @@ -61,7 +61,7 @@ public function __invoke(ServerRequestInterface $request): CallToolResult $result['output'] ?? 'No output', ); - if (isset($result['commands']) && \is_array($result['commands'])) { + if (isset($result['commands']) && \is_array(value: $result['commands'])) { $commandsOutput = []; foreach ($result['commands'] as $commandResult) { $commandsOutput[] = \sprintf( @@ -74,7 +74,7 @@ public function __invoke(ServerRequestInterface $request): CallToolResult } if (!empty($commandsOutput)) { - $output .= "\n\n## Command Details\n\n" . \implode("\n---\n", $commandsOutput); + $output .= "\n\n## Command Details\n\n" . \implode(separator: "\n---\n", array: $commandsOutput); } } diff --git a/src/McpServer/Action/Tools/Filesystem/DirectoryListAction.php b/src/McpServer/Action/Tools/Filesystem/DirectoryListAction.php index 8bb02b24..58fc8f48 100644 --- a/src/McpServer/Action/Tools/Filesystem/DirectoryListAction.php +++ b/src/McpServer/Action/Tools/Filesystem/DirectoryListAction.php @@ -39,60 +39,60 @@ public function __invoke(DirectoryListRequest $request): CallToolResult $path = (string) $this->dirs->getRootPath()->join($relativePath); if (empty($path)) { - return ToolResult::error('Missing path parameter'); + return ToolResult::error(error: 'Missing path parameter'); } try { - if (!\file_exists($path)) { - return ToolResult::error(\sprintf("Path '%s' does not exist", $relativePath)); + if (!\file_exists(filename: $path)) { + return ToolResult::error(error: \sprintf("Path '%s' does not exist", $relativePath)); } - if (!\is_dir($path)) { - return ToolResult::error(\sprintf("Path '%s' is not a directory", $relativePath)); + if (!\is_dir(filename: $path)) { + return ToolResult::error(error: \sprintf("Path '%s' is not a directory", $relativePath)); } // Create and configure Symfony Finder $finder = new Finder(); - $finder->in($path); + $finder->in(dirs: $path); // Apply pattern filter if provided if (!empty($request->pattern)) { - $patterns = \array_map(\trim(...), \explode(',', $request->pattern)); - $finder->name($patterns); + $patterns = \array_map(callback: \trim(...), array: \explode(separator: ',', string: $request->pattern)); + $finder->name(patterns: $patterns); } // Apply depth filter if provided $depth = $request->depth; - $finder->depth('<= ' . $depth); + $finder->depth(levels: '<= ' . $depth); // Apply size filter if provided if (!empty($request->size)) { - $finder->size($request->size); + $finder->size(sizes: $request->size); } // Apply date filter if provided if (!empty($request->date)) { - $finder->date($request->date); + $finder->date(dates: $request->date); } // Apply content filter if provided if (!empty($request->contains)) { - $finder->contains($request->contains); + $finder->contains(patterns: $request->contains); } // Apply type filter if provided - $type = \strtolower($request->type); + $type = \strtolower(string: $request->type); if ($type === 'file') { $finder->files(); } elseif ($type === 'directory') { $finder->directories(); } else { // Default: include both files and directories - $finder->ignoreDotFiles(false); + $finder->ignoreDotFiles(ignoreDotFiles: false); } // Apply sorting if provided - $sort = \strtolower($request->sort); + $sort = \strtolower(string: $request->sort); match ($sort) { 'name' => $finder->sortByName(), 'type' => $finder->sortByType(), @@ -108,7 +108,7 @@ public function __invoke(DirectoryListRequest $request): CallToolResult try { foreach ($finder as $file) { - $relativePath = \str_replace((string) $this->dirs->getRootPath() . '/', '', $file->getRealPath()); + $relativePath = \str_replace(search: (string) $this->dirs->getRootPath() . '/', replace: '', subject: $file->getRealPath()); $files[] = [ 'name' => $file->getFilename(), @@ -116,7 +116,7 @@ public function __invoke(DirectoryListRequest $request): CallToolResult 'fullPath' => $file->getRealPath(), 'isDirectory' => $file->isDir(), 'size' => $file->isFile() ? $file->getSize() : null, - 'lastModified' => \date('Y-m-d H:i:s', $file->getMTime()), + 'lastModified' => \date(format: 'Y-m-d H:i:s', timestamp: $file->getMTime()), ]; $filePaths[] = $file->getRealPath(); @@ -149,9 +149,9 @@ public function __invoke(DirectoryListRequest $request): CallToolResult if (!empty($filePaths)) { $treeView = $this->treeBuilder->buildTree( - $filePaths, - (string) $this->dirs->getRootPath(), - $treeViewConfig->getOptions(), + files: $filePaths, + basePath: (string) $this->dirs->getRootPath(), + options: $treeViewConfig->getOptions(), ); } else { $treeView = "No files match the specified criteria."; @@ -160,7 +160,7 @@ public function __invoke(DirectoryListRequest $request): CallToolResult // Prepare response data $responseData = [ - 'count' => \count($files), + 'count' => \count(value: $files), 'basePath' => $relativePath, ]; @@ -170,7 +170,7 @@ public function __invoke(DirectoryListRequest $request): CallToolResult $responseData['files'] = $files; } - return ToolResult::success($responseData); + return ToolResult::success(data: $responseData); } catch (\Throwable $e) { $this->logger->error('Error listing directory', [ 'path' => $path, @@ -178,7 +178,7 @@ public function __invoke(DirectoryListRequest $request): CallToolResult 'trace' => $e->getTraceAsString(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } } diff --git a/src/McpServer/Action/Tools/Filesystem/FileApplyPatchAction.php b/src/McpServer/Action/Tools/Filesystem/FileApplyPatchAction.php index b871bcf8..799d1aa0 100644 --- a/src/McpServer/Action/Tools/Filesystem/FileApplyPatchAction.php +++ b/src/McpServer/Action/Tools/Filesystem/FileApplyPatchAction.php @@ -36,22 +36,22 @@ public function __invoke(FileApplyPatchRequest $request): CallToolResult $patch = $request->patch; // Validate patch format - if (!\str_starts_with($patch, 'diff --git a/')) { - return ToolResult::error('Invalid patch format. The patch must start with "diff --git a/".'); + if (!\str_starts_with(haystack: $patch, needle: 'diff --git a/')) { + return ToolResult::error(error: 'Invalid patch format. The patch must start with "diff --git a/".'); } if (empty($path)) { - return ToolResult::error('Missing path parameter'); + return ToolResult::error(error: 'Missing path parameter'); } if (empty($patch)) { - return ToolResult::error('Missing patch parameter'); + return ToolResult::error(error: 'Missing patch parameter'); } try { $result = $this->commandsExecutor->applyPatch($path, $patch); - return ToolResult::text($result); + return ToolResult::text(text: $result); } catch (GitCommandException $e) { $this->logger->error('Error applying git patch', [ 'path' => $path, @@ -59,14 +59,14 @@ public function __invoke(FileApplyPatchRequest $request): CallToolResult 'code' => $e->getCode(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } catch (\Throwable $e) { $this->logger->error('Unexpected error applying git patch', [ 'path' => $path, 'error' => $e->getMessage(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } } diff --git a/src/McpServer/Action/Tools/Filesystem/FileMoveAction.php b/src/McpServer/Action/Tools/Filesystem/FileMoveAction.php index d2a5417d..57555e24 100644 --- a/src/McpServer/Action/Tools/Filesystem/FileMoveAction.php +++ b/src/McpServer/Action/Tools/Filesystem/FileMoveAction.php @@ -40,24 +40,24 @@ public function __invoke(FileMoveRequest $request): CallToolResult $createDirectory = $request->createDirectory; if (empty($source)) { - return ToolResult::error('Missing source parameter'); + return ToolResult::error(error: 'Missing source parameter'); } if (empty($destination)) { - return ToolResult::error('Missing destination parameter'); + return ToolResult::error(error: 'Missing destination parameter'); } try { if (!$this->files->exists($source)) { - return ToolResult::error(\sprintf("Source file '%s' does not exist", $source)); + return ToolResult::error(error: \sprintf("Source file '%s' does not exist", $source)); } // Ensure destination directory exists if requested if ($createDirectory) { - $directory = \dirname($destination); + $directory = \dirname(path: $destination); if (!$this->files->exists($directory)) { if (!$this->files->ensureDirectory($directory)) { - return ToolResult::error(\sprintf("Could not create directory '%s'", $directory)); + return ToolResult::error(error: \sprintf("Could not create directory '%s'", $directory)); } } } @@ -66,13 +66,13 @@ public function __invoke(FileMoveRequest $request): CallToolResult try { $content = $this->files->read($source); } catch (FilesException) { - return ToolResult::error(\sprintf("Could not read source file '%s'", $source)); + return ToolResult::error(error: \sprintf("Could not read source file '%s'", $source)); } // Write to destination $writeSuccess = $this->files->write($destination, $content); if (!$writeSuccess) { - return ToolResult::error(\sprintf("Could not write to destination file '%s'", $destination)); + return ToolResult::error(error: \sprintf("Could not write to destination file '%s'", $destination)); } // Delete source file @@ -80,7 +80,7 @@ public function __invoke(FileMoveRequest $request): CallToolResult if (!$deleteSuccess) { // Even if delete fails, the move operation is partially successful return ToolResult::text( - \sprintf( + text: \sprintf( "Warning: File copied to '%s' but could not delete source file '%s'", $destination, $source, @@ -88,7 +88,7 @@ public function __invoke(FileMoveRequest $request): CallToolResult ); } - return ToolResult::text(\sprintf("Successfully moved '%s' to '%s'", $source, $destination)); + return ToolResult::text(text: \sprintf("Successfully moved '%s' to '%s'", $source, $destination)); } catch (\Throwable $e) { $this->logger->error('Error moving file', [ 'source' => $source, @@ -96,7 +96,7 @@ public function __invoke(FileMoveRequest $request): CallToolResult 'error' => $e->getMessage(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } } diff --git a/src/McpServer/Action/Tools/Filesystem/FileReadAction.php b/src/McpServer/Action/Tools/Filesystem/FileReadAction.php index f00d77b7..8a59eac1 100644 --- a/src/McpServer/Action/Tools/Filesystem/FileReadAction.php +++ b/src/McpServer/Action/Tools/Filesystem/FileReadAction.php @@ -38,32 +38,32 @@ public function __invoke(FileReadRequest $request): CallToolResult $path = (string) $this->dirs->getRootPath()->join($request->path); if (empty($path)) { - return ToolResult::error('Missing path parameter'); + return ToolResult::error(error: 'Missing path parameter'); } try { if (!$this->files->exists($path)) { - return ToolResult::error(\sprintf("File '%s' does not exist", $path)); + return ToolResult::error(error: \sprintf("File '%s' does not exist", $path)); } - if (\is_dir($path)) { - return ToolResult::error(\sprintf("'%s' is a directory", $path)); + if (\is_dir(filename: $path)) { + return ToolResult::error(error: \sprintf("'%s' is a directory", $path)); } try { $content = $this->files->read($path); } catch (FilesException) { - return ToolResult::error(\sprintf("Could not read file '%s'", $path)); + return ToolResult::error(error: \sprintf("Could not read file '%s'", $path)); } - return ToolResult::text($content); + return ToolResult::text(text: $content); } catch (\Throwable $e) { $this->logger->error('Error reading file', [ 'path' => $path, 'error' => $e->getMessage(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } } diff --git a/src/McpServer/Action/Tools/Filesystem/FileWriteAction.php b/src/McpServer/Action/Tools/Filesystem/FileWriteAction.php index 2a02a275..2f7a48d3 100644 --- a/src/McpServer/Action/Tools/Filesystem/FileWriteAction.php +++ b/src/McpServer/Action/Tools/Filesystem/FileWriteAction.php @@ -37,38 +37,38 @@ public function __invoke(FileWriteRequest $request): CallToolResult $path = (string) $this->dirs->getRootPath()->join($request->path); if (empty($path)) { - return ToolResult::error('Missing path parameter'); + return ToolResult::error(error: 'Missing path parameter'); } try { // Ensure directory exists if requested if ($request->createDirectory) { - $directory = \dirname($path); + $directory = \dirname(path: $path); if (!$this->files->exists($directory)) { if (!$this->files->ensureDirectory($directory)) { - return ToolResult::error(\sprintf("Could not create directory '%s'", $directory)); + return ToolResult::error(error: \sprintf("Could not create directory '%s'", $directory)); } } } - if (\is_dir($path)) { - return ToolResult::error(\sprintf("'%s' is a directory", $path)); + if (\is_dir(filename: $path)) { + return ToolResult::error(error: \sprintf("'%s' is a directory", $path)); } $success = $this->files->write($path, $request->content); if (!$success) { - return ToolResult::error(\sprintf("Could not write to file '%s'", $path)); + return ToolResult::error(error: \sprintf("Could not write to file '%s'", $path)); } - return ToolResult::text(\sprintf("Successfully wrote %d bytes to file '%s'", \strlen($request->content), $path)); + return ToolResult::text(text: \sprintf("Successfully wrote %d bytes to file '%s'", \strlen(string: $request->content), $path)); } catch (\Throwable $e) { $this->logger->error('Error writing file', [ 'path' => $path, 'error' => $e->getMessage(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } } diff --git a/src/McpServer/Action/Tools/Git/GitAddAction.php b/src/McpServer/Action/Tools/Git/GitAddAction.php index fc882b09..27738707 100644 --- a/src/McpServer/Action/Tools/Git/GitAddAction.php +++ b/src/McpServer/Action/Tools/Git/GitAddAction.php @@ -39,12 +39,12 @@ public function __invoke(GitAddRequest $request): CallToolResult // Check if we're in a valid git repository if (!$this->commandsExecutor->isValidRepository($repository)) { - return ToolResult::error('Not a git repository (or any of the parent directories)'); + return ToolResult::error(error: 'Not a git repository (or any of the parent directories)'); } // Validate that paths are provided if (empty($request->paths)) { - return ToolResult::error('No paths specified for staging'); + return ToolResult::error(error: 'No paths specified for staging'); } try { @@ -61,16 +61,16 @@ public function __invoke(GitAddRequest $request): CallToolResult // Add the specified paths $commandParts = \array_merge($commandParts, $request->paths); - $command = new Command($repository, $commandParts); + $command = new Command(repository: $repository, command: $commandParts); $result = $this->commandsExecutor->executeString($command); // If no output, provide feedback about what was staged - if (empty(\trim($result))) { - $stagedInfo = $this->getStagedFilesInfo($repository, $request->paths); + if (empty(\trim(string: $result))) { + $stagedInfo = $this->getStagedFilesInfo(repository: $repository, paths: $request->paths); $result = $stagedInfo ?: 'Files staged successfully'; } - return ToolResult::text($result); + return ToolResult::text(text: $result); } catch (GitCommandException $e) { $this->logger->error('Error executing git add', [ 'repository' => $repository, @@ -79,7 +79,7 @@ public function __invoke(GitAddRequest $request): CallToolResult 'code' => $e->getCode(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } catch (\Throwable $e) { $this->logger->error('Unexpected error during git add', [ 'repository' => $repository, @@ -87,7 +87,7 @@ public function __invoke(GitAddRequest $request): CallToolResult 'error' => $e->getMessage(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } @@ -95,13 +95,13 @@ private function getStagedFilesInfo(string $repository, array $paths): ?string { try { // Get list of staged files - $command = new Command($repository, ['diff', '--cached', '--name-status']); + $command = new Command(repository: $repository, command: ['diff', '--cached', '--name-status']); $stagedFiles = $this->commandsExecutor->executeString($command); - if (!empty(\trim($stagedFiles))) { - $lines = \explode("\n", \trim($stagedFiles)); - $fileCount = \count($lines); - $pathsDescription = \count($paths) === 1 && $paths[0] === '.' ? 'all files' : \implode(', ', $paths); + if (!empty(\trim(string: $stagedFiles))) { + $lines = \explode(separator: "\n", string: \trim(string: $stagedFiles)); + $fileCount = \count(value: $lines); + $pathsDescription = \count(value: $paths) === 1 && $paths[0] === '.' ? 'all files' : \implode(separator: ', ', array: $paths); return \sprintf( "Staged %d file(s) from %s:\n%s", diff --git a/src/McpServer/Action/Tools/Git/GitCommitAction.php b/src/McpServer/Action/Tools/Git/GitCommitAction.php index 6995e91c..422e2de3 100644 --- a/src/McpServer/Action/Tools/Git/GitCommitAction.php +++ b/src/McpServer/Action/Tools/Git/GitCommitAction.php @@ -39,12 +39,12 @@ public function __invoke(GitCommitRequest $request): CallToolResult // Check if we're in a valid git repository if (!$this->commandsExecutor->isValidRepository($repository)) { - return ToolResult::error('Not a git repository (or any of the parent directories)'); + return ToolResult::error(error: 'Not a git repository (or any of the parent directories)'); } // Validate commit message - if (empty(\trim($request->message))) { - return ToolResult::error('Commit message cannot be empty'); + if (empty(\trim(string: $request->message))) { + return ToolResult::error(error: 'Commit message cannot be empty'); } try { @@ -60,14 +60,14 @@ public function __invoke(GitCommitRequest $request): CallToolResult } // Check if there are changes to commit (unless allowEmpty is true) - if (!$this->hasChangesToCommit($repository, $request->stageAll)) { - return ToolResult::error('No changes to commit. Use git-add to stage files or enable stageAll option'); + if (!$this->hasChangesToCommit(repository: $repository, stageAll: $request->stageAll)) { + return ToolResult::error(error: 'No changes to commit. Use git-add to stage files or enable stageAll option'); } - $command = new Command($repository, $commandParts); + $command = new Command(repository: $repository, command: $commandParts); $result = $this->commandsExecutor->executeString($command); - return ToolResult::text($result); + return ToolResult::text(text: $result); } catch (GitCommandException $e) { $this->logger->error('Error executing git commit', [ 'repository' => $repository, @@ -76,7 +76,7 @@ public function __invoke(GitCommitRequest $request): CallToolResult 'code' => $e->getCode(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } catch (\Throwable $e) { $this->logger->error('Unexpected error during git commit', [ 'repository' => $repository, @@ -84,7 +84,7 @@ public function __invoke(GitCommitRequest $request): CallToolResult 'error' => $e->getMessage(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } @@ -93,14 +93,14 @@ private function hasChangesToCommit(string $repository, bool $stageAll): bool try { if ($stageAll) { // Check if there are any tracked files with changes - $statusCommand = new Command($repository, ['status', '--porcelain']); + $statusCommand = new Command(repository: $repository, command: ['status', '--porcelain']); $status = $this->commandsExecutor->executeString($statusCommand); - return !empty(\trim($status)); + return !empty(\trim(string: $status)); } // Check if there are staged changes - $diffCommand = new Command($repository, ['diff', '--cached', '--name-only']); + $diffCommand = new Command(repository: $repository, command: ['diff', '--cached', '--name-only']); $stagedFiles = $this->commandsExecutor->executeString($diffCommand); - return !empty(\trim($stagedFiles)); + return !empty(\trim(string: $stagedFiles)); } catch (\Throwable) { // If we can't check, assume there might be changes to avoid blocking return true; diff --git a/src/McpServer/Action/Tools/Git/GitStatusAction.php b/src/McpServer/Action/Tools/Git/GitStatusAction.php index 72013ec2..c8aaf534 100644 --- a/src/McpServer/Action/Tools/Git/GitStatusAction.php +++ b/src/McpServer/Action/Tools/Git/GitStatusAction.php @@ -40,7 +40,7 @@ public function __invoke(GitStatusRequest $request): CallToolResult // Check if we're in a valid git repository if (!$this->commandsExecutor->isValidRepository($repository)) { - return ToolResult::error('Not a git repository (or any of the parent directories)'); + return ToolResult::error(error: 'Not a git repository (or any of the parent directories)'); } try { @@ -66,20 +66,20 @@ public function __invoke(GitStatusRequest $request): CallToolResult $commandParts[] = '--untracked-files=no'; } - $command = new Command($repository, $commandParts); + $command = new Command(repository: $repository, command: $commandParts); $result = $this->commandsExecutor->executeString($command); // If result is empty, indicate clean working tree - if (empty(\trim($result))) { + if (empty(\trim(string: $result))) { $result = \sprintf( 'On branch %s nothing to commit, working tree clean', $this->getCurrentBranch( - $repository, + repository: $repository, ), ); } - return ToolResult::text($result); + return ToolResult::text(text: $result); } catch (GitCommandException $e) { $this->logger->error('Error executing git status', [ 'repository' => $repository, @@ -87,22 +87,22 @@ public function __invoke(GitStatusRequest $request): CallToolResult 'code' => $e->getCode(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } catch (\Throwable $e) { $this->logger->error('Unexpected error during git status', [ 'repository' => $repository, 'error' => $e->getMessage(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } private function getCurrentBranch(string $repository): string { try { - $command = new Command($repository, ['branch', '--show-current']); - $branch = \trim($this->commandsExecutor->executeString($command)); + $command = new Command(repository: $repository, command: ['branch', '--show-current']); + $branch = \trim(string: $this->commandsExecutor->executeString($command)); return !empty($branch) ? $branch : 'HEAD'; } catch (\Throwable) { return 'HEAD'; diff --git a/src/McpServer/Action/Tools/ListToolsAction.php b/src/McpServer/Action/Tools/ListToolsAction.php index 413551f6..2b10e020 100644 --- a/src/McpServer/Action/Tools/ListToolsAction.php +++ b/src/McpServer/Action/Tools/ListToolsAction.php @@ -26,17 +26,17 @@ public function __invoke(ServerRequestInterface $request): ListToolsResult { $this->logger->info('Listing available tools'); - $tools = \array_values($this->provider->getTools()); + $tools = \array_values(array: $this->provider->getTools()); foreach ($this->toolProvider->all() as $toolDefinition) { $tools[] = new Tool( name: $toolDefinition->id, - inputSchema: $this->buildInputSchema($toolDefinition), + inputSchema: $this->buildInputSchema(toolDefinition: $toolDefinition), description: $toolDefinition->description, annotations: null, ); } - return new ListToolsResult($tools); + return new ListToolsResult(tools: $tools); } /** diff --git a/src/McpServer/Action/Tools/Prompts/GetPromptToolAction.php b/src/McpServer/Action/Tools/Prompts/GetPromptToolAction.php index 680ef6f8..a7ec46d7 100644 --- a/src/McpServer/Action/Tools/Prompts/GetPromptToolAction.php +++ b/src/McpServer/Action/Tools/Prompts/GetPromptToolAction.php @@ -40,18 +40,18 @@ public function __invoke(GetPromptRequest $request, ServerRequestInterface $serv $id = $request->id; if (empty($id)) { - return ToolResult::error('Missing prompt ID parameter'); + return ToolResult::error(error: 'Missing prompt ID parameter'); } try { // Check if prompt exists if (!$this->prompts->has($id)) { - return ToolResult::error(\sprintf("Prompt with ID '%s' not found", $id)); + return ToolResult::error(error: \sprintf("Prompt with ID '%s' not found", $id)); } // Get prompt and process messages $prompt = $this->prompts->get($id); - $messages = $this->processMessageTemplates($prompt->messages, $serverRequest->getAttributes()); + $messages = $this->processMessageTemplates(messages: $prompt->messages, arguments: $serverRequest->getAttributes()); // Format the messages for return $formattedMessages = []; @@ -63,7 +63,7 @@ public function __invoke(GetPromptRequest $request, ServerRequestInterface $serv ]; } - return ToolResult::success([ + return ToolResult::success(data: [ 'id' => $id, 'description' => $prompt->prompt->description, 'messages' => $formattedMessages, @@ -75,7 +75,7 @@ public function __invoke(GetPromptRequest $request, ServerRequestInterface $serv 'trace' => $e->getTraceAsString(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } @@ -89,25 +89,25 @@ public function __invoke(GetPromptRequest $request, ServerRequestInterface $serv private function processMessageTemplates(array $messages, array $arguments): array { $arguments = \array_combine( - \array_map(static fn($key) => '{{' . $key . '}}', \array_keys($arguments)), - \array_values($arguments), + keys: \array_map(callback: static fn($key) => '{{' . $key . '}}', array: \array_keys(array: $arguments)), + values: \array_values(array: $arguments), ); $variables = $this->variables; - return \array_map(static function ($message) use ($variables, $arguments) { + return \array_map(callback: static function ($message) use ($variables, $arguments) { $content = $message->content; if ($content instanceof TextContent) { $text = \strtr($content->text, $arguments); - $text = $variables->resolve($text); + $text = $variables->resolve(strings: $text); - $content = new TextContent($text); + $content = new TextContent(text: $text); } return new PromptMessage( role: $message->role, content: $content, ); - }, $messages); + }, array: $messages); } } diff --git a/src/McpServer/Action/Tools/Prompts/ListPromptsToolAction.php b/src/McpServer/Action/Tools/Prompts/ListPromptsToolAction.php index da87c46e..ef447a24 100644 --- a/src/McpServer/Action/Tools/Prompts/ListPromptsToolAction.php +++ b/src/McpServer/Action/Tools/Prompts/ListPromptsToolAction.php @@ -54,8 +54,8 @@ public function __invoke(ServerRequestInterface $request): CallToolResult ]; } - return ToolResult::success([ - 'count' => \count($promptsList), + return ToolResult::success(data: [ + 'count' => \count(value: $promptsList), 'prompts' => $promptsList, ]); } catch (\Throwable $e) { @@ -64,7 +64,7 @@ public function __invoke(ServerRequestInterface $request): CallToolResult 'trace' => $e->getTraceAsString(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } } diff --git a/src/McpServer/ActionsBootloader.php b/src/McpServer/ActionsBootloader.php index 597331e6..0d1c1c4d 100644 --- a/src/McpServer/ActionsBootloader.php +++ b/src/McpServer/ActionsBootloader.php @@ -139,8 +139,8 @@ public function defineSingletons(): array ) { $loader->load(); - foreach ($this->actions($config) as $action) { - $factory->registerAction($action); + foreach ($this->actions(config: $config) as $action) { + $factory->registerAction(class: $action); } return $factory; @@ -253,6 +253,6 @@ private function actions(McpConfig $config): array ]; } - return \array_unique($actions); + return \array_unique(array: $actions); } } diff --git a/src/McpServer/Console/MCPServerCommand.php b/src/McpServer/Console/MCPServerCommand.php index b0599bb8..551fba96 100644 --- a/src/McpServer/Console/MCPServerCommand.php +++ b/src/McpServer/Console/MCPServerCommand.php @@ -86,7 +86,7 @@ public function __invoke( ->determineRootPath($this->configPath) ->withEnvFile($this->envFileName); - $binder = $container->getBinder('root'); + $binder = $container->getBinder(scope: 'root'); $binder->bind( DirectoriesInterface::class, $dirs, @@ -128,14 +128,14 @@ public function __invoke( try { // Get the appropriate loader based on options provided - if (!\is_dir($rootPathStr)) { + if (!\is_dir(filename: $rootPathStr)) { $logger->info( 'Loading configuration from provided path...', [ 'path' => $rootPathStr, ], ); - $loader = $configProvider->fromPath((string) $dirs->getConfigPath()); + $loader = $configProvider->fromPath(configPath: (string) $dirs->getConfigPath()); } else { $logger->info('Using default configuration location...'); $loader = $configProvider->fromDefaultLocation(); @@ -155,7 +155,7 @@ public function __invoke( DirectoriesInterface::class => $dirs, HasPrefixLoggerInterface::class => $logger, ConfigLoaderInterface::class => $loader, - CommandExecutorInterface::class => $container->make(CommandExecutor::class, [ + CommandExecutorInterface::class => $container->make(alias: CommandExecutor::class, parameters: [ 'projectRoot' => (string) $dirs->getRootPath(), ]), EnvironmentInterface::class => $env, diff --git a/src/McpServer/Console/McpConfigCommand.php b/src/McpServer/Console/McpConfigCommand.php index 7fa8345e..3211f181 100644 --- a/src/McpServer/Console/McpConfigCommand.php +++ b/src/McpServer/Console/McpConfigCommand.php @@ -66,19 +66,19 @@ public function __invoke( ConfigGeneratorInterface $configGenerator, DirectoriesInterface $dirs, ): int { - $renderer = new McpConfigRenderer($this->output); + $renderer = new McpConfigRenderer(output: $this->output); $renderer->renderHeader(); // Handle interactive mode if ($this->interactive) { - return $this->runInteractiveMode($osDetection, $configGenerator, $renderer, $dirs); + return $this->runInteractiveMode(osDetection: $osDetection, configGenerator: $configGenerator, renderer: $renderer, dirs: $dirs); } // Detect operating system and environment - $osInfo = $osDetection->detect($this->forceWsl); + $osInfo = $osDetection->detect(forceWsl: $this->forceWsl); // Determine configuration approach - $options = $this->buildConfigOptions($dirs); + $options = $this->buildConfigOptions(dirs: $dirs); // Generate configuration $config = $configGenerator->generate( @@ -89,11 +89,11 @@ public function __invoke( ); // Render the configuration - $renderer->renderConfiguration($config, $osInfo, $options); + $renderer->renderConfiguration(config: $config, osInfo: $osInfo, options: $options); // Show explanations if requested if ($this->explain) { - $renderer->renderExplanation($config, $osInfo, $options); + $renderer->renderExplanation(config: $config, osInfo: $osInfo, options: $options); } return Command::SUCCESS; @@ -116,7 +116,7 @@ private function runInteractiveMode( // Auto-detect OS $osInfo = $osDetection->detect(); - $renderer->renderDetectedEnvironment($osInfo); + $renderer->renderDetectedEnvironment(osInfo: $osInfo); // Ask about WSL if on Windows if ($osInfo->isWindows() && !$osInfo->isWsl()) { @@ -154,7 +154,7 @@ private function runInteractiveMode( ); // Validate project path - if (!\is_dir($projectPath)) { + if (!\is_dir(filename: $projectPath)) { $this->output->warning("Warning: The specified path does not exist: {$projectPath}"); if (!$this->output->confirm('Continue anyway?', true)) { @@ -180,8 +180,8 @@ private function runInteractiveMode( options: $options, ); - $renderer->renderConfiguration($config, $osInfo, $options); - $renderer->renderExplanation($config, $osInfo, $options); + $renderer->renderConfiguration(config: $config, osInfo: $osInfo, options: $options); + $renderer->renderExplanation(config: $config, osInfo: $osInfo, options: $options); return Command::SUCCESS; } diff --git a/src/McpServer/HttpTransportBootloader.php b/src/McpServer/HttpTransportBootloader.php index 9323271a..a75d85f1 100644 --- a/src/McpServer/HttpTransportBootloader.php +++ b/src/McpServer/HttpTransportBootloader.php @@ -68,7 +68,7 @@ public function defineSingletons(): array ) { $store = new InMemoryClientRepository(); $store->registerClient( - new OAuthClientInformation( + client: new OAuthClientInformation( clientId: $env->get('OAUTH_CLIENT_ID'), clientSecret: $env->get('OAUTH_CLIENT_SECRET'), clientIdIssuedAt: \time(), @@ -203,7 +203,7 @@ public function boot( ): void { $convertValues = static fn( string|null|bool $values, - ) => \is_string($values) ? \array_map(\trim(...), \explode(',', $values)) : []; + ) => \is_string(value: $values) ? \array_map(callback: \trim(...), array: \explode(separator: ',', string: $values)) : []; // Get allowed origins from env or use wildcard $allowedOrigins = $convertValues($env->get('MCP_CORS_ALLOWED_ORIGINS', '*')); diff --git a/src/McpServer/Middleware/AuthMiddleware.php b/src/McpServer/Middleware/AuthMiddleware.php index 1358c638..9d9f6453 100644 --- a/src/McpServer/Middleware/AuthMiddleware.php +++ b/src/McpServer/Middleware/AuthMiddleware.php @@ -30,7 +30,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface bindings: new Scope( name: AppScope::McpOauth, bindings: [ - UserProviderInterface::class => new InMemoryUserProvider($auth), + UserProviderInterface::class => new InMemoryUserProvider(authInfo: $auth), ], ), scope: static fn() => $handler->handle($request), diff --git a/src/McpServer/Projects/Actions/Dto/ProjectSwitchResponse.php b/src/McpServer/Projects/Actions/Dto/ProjectSwitchResponse.php index 96761633..a09f27b6 100644 --- a/src/McpServer/Projects/Actions/Dto/ProjectSwitchResponse.php +++ b/src/McpServer/Projects/Actions/Dto/ProjectSwitchResponse.php @@ -18,11 +18,11 @@ public function __construct( public function jsonSerialize(): array { - return \array_filter([ + return \array_filter(array: [ 'success' => $this->success, 'message' => $this->message, 'current_project' => $this->currentProject, 'resolved_from_alias' => $this->resolvedFromAlias, - ], static fn($value) => $value !== null); + ], callback: static fn($value) => $value !== null); } } diff --git a/src/McpServer/Projects/Actions/ProjectSwitchToolAction.php b/src/McpServer/Projects/Actions/ProjectSwitchToolAction.php index 8c0741a5..dc010652 100644 --- a/src/McpServer/Projects/Actions/ProjectSwitchToolAction.php +++ b/src/McpServer/Projects/Actions/ProjectSwitchToolAction.php @@ -41,7 +41,7 @@ public function __invoke(ProjectSwitchRequest $request): CallToolResult $pathOrAlias = $request->alias; if (empty($pathOrAlias)) { - return ToolResult::error('Missing pathOrAlias parameter'); + return ToolResult::error(error: 'Missing pathOrAlias parameter'); } // Handle using an alias as the path @@ -49,27 +49,27 @@ public function __invoke(ProjectSwitchRequest $request): CallToolResult $wasAlias = $resolvedPath !== $pathOrAlias; // Normalize path to absolute path - $projectPath = $this->normalizePath($resolvedPath); + $projectPath = $this->normalizePath(path: $resolvedPath); // Check if the project exists in our registry $projects = $this->projectService->getProjects(); if (!isset($projects[$projectPath])) { - $availableProjects = \array_keys($projects); - $availableAliases = \array_keys($this->projectService->getAliases()); + $availableProjects = \array_keys(array: $projects); + $availableAliases = \array_keys(array: $this->projectService->getAliases()); $suggestions = []; if (!empty($availableProjects)) { - $suggestions[] = 'Available project paths: ' . \implode(', ', $availableProjects); + $suggestions[] = 'Available project paths: ' . \implode(separator: ', ', array: $availableProjects); } if (!empty($availableAliases)) { - $suggestions[] = 'Available aliases: ' . \implode(', ', $availableAliases); + $suggestions[] = 'Available aliases: ' . \implode(separator: ', ', array: $availableAliases); } return ToolResult::error( - \sprintf( + error: \sprintf( "Project '%s' is not registered.\n%s", $projectPath, - \implode("\n", $suggestions), + \implode(separator: "\n", array: $suggestions), ), ); } @@ -101,7 +101,7 @@ public function __invoke(ProjectSwitchRequest $request): CallToolResult resolvedFromAlias: $aliasResolution, ); - return ToolResult::success($response); + return ToolResult::success(data: $response); } $response = new ProjectSwitchResponse( @@ -109,7 +109,7 @@ public function __invoke(ProjectSwitchRequest $request): CallToolResult message: \sprintf("Failed to switch to project '%s'", $projectPath), ); - return ToolResult::error($response->message); + return ToolResult::error(error: $response->message); } catch (\Throwable $e) { $this->logger->error('Error switching project', [ 'pathOrAlias' => $request->alias, @@ -117,7 +117,7 @@ public function __invoke(ProjectSwitchRequest $request): CallToolResult 'trace' => $e->getTraceAsString(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } @@ -131,7 +131,7 @@ private function normalizePath(string $path): string return (string) FSPath::cwd(); } - $pathObj = FSPath::create($path); + $pathObj = FSPath::create(path: $path); // If path is relative, make it absolute from the current directory if ($pathObj->isRelative()) { diff --git a/src/McpServer/Projects/Actions/ProjectsListToolAction.php b/src/McpServer/Projects/Actions/ProjectsListToolAction.php index fe65e30b..71d5476b 100644 --- a/src/McpServer/Projects/Actions/ProjectsListToolAction.php +++ b/src/McpServer/Projects/Actions/ProjectsListToolAction.php @@ -45,7 +45,7 @@ public function __invoke(ServerRequestInterface $request): CallToolResult message: 'No projects registered. Use project:add command to add projects.', ); - return ToolResult::success($response); + return ToolResult::success(data: $response); } // Create inverse alias map for quick lookups @@ -84,17 +84,17 @@ public function __invoke(ServerRequestInterface $request): CallToolResult $response = new ProjectsListResponse( projects: $projectInfos, currentProject: $currentProjectResponse, - totalProjects: \count($projects), + totalProjects: \count(value: $projects), ); - return ToolResult::success($response); + return ToolResult::success(data: $response); } catch (\Throwable $e) { $this->logger->error('Error listing projects', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); - return ToolResult::error($e->getMessage()); + return ToolResult::error(error: $e->getMessage()); } } } diff --git a/src/McpServer/Projects/Console/ProjectAddCommand.php b/src/McpServer/Projects/Console/ProjectAddCommand.php index 3803fa9f..a44f55b2 100644 --- a/src/McpServer/Projects/Console/ProjectAddCommand.php +++ b/src/McpServer/Projects/Console/ProjectAddCommand.php @@ -66,7 +66,7 @@ public function __invoke( } // Normalize path to absolute path - $projectPath = $this->normalizePath($this->path, $dirs); + $projectPath = $this->normalizePath(path: $this->path, dirs: $dirs); // Validate project path if (!$files->exists($projectPath)) { @@ -81,7 +81,7 @@ public function __invoke( // Validate env file path if provided if ($this->envFile !== null) { - $envPath = FSPath::create($projectPath)->join($this->envFile)->toString(); + $envPath = FSPath::create(path: $projectPath)->join($this->envFile)->toString(); if (!$files->exists($envPath)) { $this->output->warning(\sprintf("Env file does not exist: %s", $envPath)); // Not returning failure here, just warning the user @@ -128,7 +128,7 @@ public function __invoke( } // If this is the first project, also set it as the current project - if (\count($projectService->getProjects()) === 1) { + if (\count(value: $projectService->getProjects()) === 1) { $projectService->setCurrentProject($projectPath, $this->name, $this->configFile, $this->envFile); $this->output->info('Project was automatically set as the current project (first project added).'); } @@ -146,7 +146,7 @@ private function normalizePath(string $path, DirectoriesInterface $dirs): string return (string) FSPath::cwd(); } - $pathObj = FSPath::create($path); + $pathObj = FSPath::create(path: $path); // If path is relative, make it absolute from the current directory if ($pathObj->isRelative()) { diff --git a/src/McpServer/Projects/Console/ProjectCommand.php b/src/McpServer/Projects/Console/ProjectCommand.php index 39d09575..ce797030 100644 --- a/src/McpServer/Projects/Console/ProjectCommand.php +++ b/src/McpServer/Projects/Console/ProjectCommand.php @@ -30,7 +30,7 @@ public function __invoke(DirectoriesInterface $dirs, ProjectServiceInterface $pr { // If no path provided, show interactive selection or current project if ($this->path === null) { - return $this->selectProjectInteractively($projectService); + return $this->selectProjectInteractively(projectService: $projectService); } // Handle using an alias as the path @@ -41,7 +41,7 @@ public function __invoke(DirectoriesInterface $dirs, ProjectServiceInterface $pr } // Normalize path to absolute path - $projectPath = $this->normalizePath($this->path, $dirs); + $projectPath = $this->normalizePath(path: $this->path, dirs: $dirs); // First, try to switch to this project if it exists if ($projectService->switchToProject($projectPath)) { @@ -82,7 +82,7 @@ private function selectProjectInteractively(ProjectServiceInterface $projectServ $aliases = $projectService->getAliasesForPath($currentProject->path); if (!empty($aliases)) { - $this->output->text(\sprintf("Aliases: %s", \implode(', ', $aliases))); + $this->output->text(\sprintf("Aliases: %s", \implode(separator: ', ', array: $aliases))); } $this->output->newLine(); @@ -95,7 +95,7 @@ private function selectProjectInteractively(ProjectServiceInterface $projectServ foreach ($projects as $path => $_) { $aliases = $projectService->getAliasesForPath($path); - $aliasString = !empty($aliases) ? ' [' . \implode(', ', $aliases) . ']' : ''; + $aliasString = !empty($aliases) ? ' [' . \implode(separator: ', ', array: $aliases) . ']' : ''; $isCurrent = ($currentProject && $currentProject->path === $path) ? ' (CURRENT)' : ''; $displayString = \sprintf( @@ -115,16 +115,16 @@ private function selectProjectInteractively(ProjectServiceInterface $projectServ $choices[] = $cancelOption; // Create the question with all choices - $helper = $this->getHelper('question'); - \assert($helper instanceof QuestionHelper); + $helper = $this->getHelper(name: 'question'); + \assert(assertion: $helper instanceof QuestionHelper); $question = new ChoiceQuestion( - 'Select a project to switch to:', - $choices, - 0, // Default to first option + question: 'Select a project to switch to:', + choices: $choices, + default: 0, // Default to first option ); - $question->setErrorMessage('Invalid selection.'); + $question->setErrorMessage(errorMessage: 'Invalid selection.'); - $selectedChoice = $helper->ask($this->input, $this->output, $question); + $selectedChoice = $helper->ask(input: $this->input, output: $this->output, question: $question); // Handle cancel option if ($selectedChoice === $cancelOption) { @@ -156,7 +156,7 @@ private function normalizePath(string $path, DirectoriesInterface $dirs): string return (string) FSPath::cwd(); } - $pathObj = FSPath::create($path); + $pathObj = FSPath::create(path: $path); // If path is relative, make it absolute from the current directory if ($pathObj->isRelative()) { diff --git a/src/McpServer/Projects/Console/ProjectListCommand.php b/src/McpServer/Projects/Console/ProjectListCommand.php index 953090f2..ef6cd9de 100644 --- a/src/McpServer/Projects/Console/ProjectListCommand.php +++ b/src/McpServer/Projects/Console/ProjectListCommand.php @@ -41,24 +41,24 @@ public function __invoke(ProjectServiceInterface $projectService): int } // Create and configure table - $table = new Table($this->output); - $table->setHeaders(['Path', 'Config File', 'Env File', 'Aliases', 'Added', 'Current']); + $table = new Table(output: $this->output); + $table->setHeaders(headers: ['Path', 'Config File', 'Env File', 'Aliases', 'Added', 'Current']); // Add rows to table foreach ($projects as $path => $info) { $isCurrent = $currentProject && $currentProject->path === $path ? '✓' : ''; $aliasesStr = !empty($pathToAliases[$path]) - ? \implode(', ', $pathToAliases[$path]) + ? \implode(separator: ', ', array: $pathToAliases[$path]) : ''; - $table->addRow([ - Style::property($path), + $table->addRow(row: [ + Style::property(text: $path), $info->configFile ?? '', $info->envFile ?? '', $aliasesStr, $info->addedAt, - $isCurrent ? Style::highlight($isCurrent) : '', + $isCurrent ? Style::highlight(text: $isCurrent) : '', ]); } diff --git a/src/McpServer/Prompt/Console/ListPromptsCommand.php b/src/McpServer/Prompt/Console/ListPromptsCommand.php index 24b29e5e..83e842c7 100644 --- a/src/McpServer/Prompt/Console/ListPromptsCommand.php +++ b/src/McpServer/Prompt/Console/ListPromptsCommand.php @@ -87,7 +87,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int // Get the appropriate loader based on options provided if ($this->configPath !== null) { $this->logger->info(\sprintf('Loading configuration from %s...', $this->configPath)); - $loader = $configProvider->fromPath($this->configPath); + $loader = $configProvider->fromPath(configPath: $this->configPath); } else { $this->logger->info('Loading configuration from default location...'); $loader = $configProvider->fromDefaultLocation(); @@ -109,7 +109,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int $prompts = $promptProvider->all(); // Create filter based on command options - $filter = $this->createFilter($filterFactory); + $filter = $this->createFilter(filterFactory: $filterFactory); // Apply filter if needed if ($filter !== null) { @@ -133,7 +133,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int } // Display prompts based on the selected format - return $this->displayAsTable($prompts); + return $this->displayAsTable(prompts: $prompts); }, ); } @@ -164,7 +164,7 @@ private function createFilter(PromptFilterFactory $filterFactory): ?PromptFilter } } - return $filterFactory->createFromConfig($filterConfig); + return $filterFactory->createFromConfig(filterConfig: $filterConfig); } /** @@ -176,44 +176,44 @@ private function displayAsTable(array $prompts): int $title = 'Available Prompts'; $this->output->title($title); - $table = new Table($this->output); + $table = new Table(output: $this->output); if ($this->detailed) { - $table->setHeaders(['ID', 'Type', 'Description', 'Tags', 'Arguments']); + $table->setHeaders(headers: ['ID', 'Type', 'Description', 'Tags', 'Arguments']); } else { - $table->setHeaders(['ID', 'Type', 'Description', 'Tags']); + $table->setHeaders(headers: ['ID', 'Type', 'Description', 'Tags']); } foreach ($prompts as $promptDef) { $row = [ - new TableCell($promptDef->id, ['style' => new TableCellStyle(['fg' => 'cyan'])]), + new TableCell(value: $promptDef->id, options: ['style' => new TableCellStyle(options: ['fg' => 'cyan'])]), new TableCell( - $promptDef->type->value, - [ + value: $promptDef->type->value, + options: [ 'style' => new TableCellStyle( - ['fg' => $promptDef->type === PromptType::Prompt ? 'green' : 'blue'], + options: ['fg' => $promptDef->type === PromptType::Prompt ? 'green' : 'blue'], ), ], ), $promptDef->prompt->description ?? '-', - \implode(', ', $promptDef->tags), + \implode(separator: ', ', array: $promptDef->tags), ]; if ($this->detailed) { - $args = $this->formatArguments($promptDef->prompt); + $args = $this->formatArguments(prompt: $promptDef->prompt); $row[] = $args; } - $table->addRow($row); + $table->addRow(row: $row); if ($this->detailed) { - $table->addRow(new TableSeparator()); + $table->addRow(row: new TableSeparator()); } } $table->render(); $this->output->writeln(''); - $this->output->writeln(\sprintf('%s: %s', Style::property('Total prompts'), Style::count(\count($prompts)))); + $this->output->writeln(\sprintf('%s: %s', Style::property(text: 'Total prompts'), Style::count(count: \count(value: $prompts)))); return Command::SUCCESS; } @@ -241,6 +241,6 @@ private function formatArguments(Prompt $prompt): string $args[] = $name; } - return \implode("\n", $args); + return \implode(separator: "\n", array: $args); } } diff --git a/src/McpServer/Prompt/Console/ShowPromptCommand.php b/src/McpServer/Prompt/Console/ShowPromptCommand.php index da1db1fa..3b4d4297 100644 --- a/src/McpServer/Prompt/Console/ShowPromptCommand.php +++ b/src/McpServer/Prompt/Console/ShowPromptCommand.php @@ -67,7 +67,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int // Get the appropriate loader based on options provided if ($this->configPath !== null) { $this->logger->info(\sprintf('Loading configuration from %s...', $this->configPath)); - $loader = $configProvider->fromPath($this->configPath); + $loader = $configProvider->fromPath(configPath: $this->configPath); } else { $this->logger->info('Loading configuration from default location...'); $loader = $configProvider->fromDefaultLocation(); @@ -90,7 +90,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int $this->output->error(\sprintf('Prompt with ID "%s" not found.', $this->promptId)); // Suggest similar prompts - $this->suggestSimilarPrompts($promptProvider); + $this->suggestSimilarPrompts(promptProvider: $promptProvider); return Command::FAILURE; } @@ -99,7 +99,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int $prompt = $promptProvider->get($this->promptId); // Display prompt details - return $this->displayPromptDetails($prompt); + return $this->displayPromptDetails(prompt: $prompt); }, ); } @@ -112,16 +112,16 @@ private function displayPromptDetails(PromptDefinition $prompt): int $this->output->title(\sprintf('Prompt: %s', $prompt->id)); // Basic information table - $this->displayBasicInfo($prompt); + $this->displayBasicInfo(prompt: $prompt); // Arguments table if (!empty($prompt->prompt->arguments)) { - $this->displayArguments($prompt->prompt); + $this->displayArguments(prompt: $prompt->prompt); } // Messages if ($this->withMessages && !empty($prompt->messages)) { - $this->displayMessages($prompt); + $this->displayMessages(prompt: $prompt); } return Command::SUCCESS; @@ -133,14 +133,14 @@ private function displayPromptDetails(PromptDefinition $prompt): int private function displayBasicInfo(PromptDefinition $prompt): void { $this->output->writeln(''); - $this->output->writeln(Style::section('Basic Information')); + $this->output->writeln(Style::section(text: 'Basic Information')); - $table = new Table($this->output); - $table->setStyle('box'); + $table = new Table(output: $this->output); + $table->setStyle(name: 'box'); $rows = [ ['ID', $prompt->id], - ['Type', $this->formatPromptType($prompt->type)], + ['Type', $this->formatPromptType(type: $prompt->type)], ]; if ($prompt->prompt->description !== null) { @@ -148,16 +148,16 @@ private function displayBasicInfo(PromptDefinition $prompt): void } if (!empty($prompt->tags)) { - $rows[] = ['Tags', \implode(', ', $prompt->tags)]; + $rows[] = ['Tags', \implode(separator: ', ', array: $prompt->tags)]; } - $rows[] = ['Messages', \count($prompt->messages)]; - $rows[] = ['Arguments', \count($prompt->prompt->arguments)]; - $rows[] = ['Extensions', \count($prompt->extensions)]; + $rows[] = ['Messages', \count(value: $prompt->messages)]; + $rows[] = ['Arguments', \count(value: $prompt->prompt->arguments)]; + $rows[] = ['Extensions', \count(value: $prompt->extensions)]; foreach ($rows as $row) { - $table->addRow([ - new TableCell($row[0], ['style' => new TableCellStyle(['fg' => 'yellow'])]), + $table->addRow(row: [ + new TableCell(value: $row[0], options: ['style' => new TableCellStyle(options: ['fg' => 'yellow'])]), $row[1], ]); } @@ -171,17 +171,17 @@ private function displayBasicInfo(PromptDefinition $prompt): void private function displayArguments(Prompt $prompt): void { $this->output->writeln(''); - $this->output->writeln(Style::section('Arguments')); + $this->output->writeln(Style::section(text: 'Arguments')); - $table = new Table($this->output); - $table->setHeaders(['Name', 'Required', 'Description']); - $table->setStyle('box'); + $table = new Table(output: $this->output); + $table->setHeaders(headers: ['Name', 'Required', 'Description']); + $table->setStyle(name: 'box'); foreach ($prompt->arguments as $arg) { - $table->addRow([ - new TableCell($arg->name, ['style' => new TableCellStyle(['fg' => 'cyan'])]), - $arg->required ? Style::success('Yes') : Style::muted('No'), - $arg->description ?? Style::muted('(no description)'), + $table->addRow(row: [ + new TableCell(value: $arg->name, options: ['style' => new TableCellStyle(options: ['fg' => 'cyan'])]), + $arg->required ? Style::success(text: 'Yes') : Style::muted(text: 'No'), + $arg->description ?? Style::muted(text: '(no description)'), ]); } @@ -194,38 +194,38 @@ private function displayArguments(Prompt $prompt): void private function displayMessages(PromptDefinition $prompt): void { $this->output->writeln(''); - $this->output->writeln(Style::section('Messages')); + $this->output->writeln(Style::section(text: 'Messages')); foreach ($prompt->messages as $index => $message) { $index = (int) $index; // Ensure index is an integer for display $this->output->writeln(''); $this->output->writeln( - \sprintf(' %s. %s', $index + 1, Style::property('Role:') . ' ' . Style::value($message->role->value)), + \sprintf(' %s. %s', $index + 1, Style::property(text: 'Role:') . ' ' . Style::value(text: $message->role->value)), ); // Show content preview (first few lines) /** @psalm-suppress UndefinedPropertyFetch */ $content = $message->content->text; - $lines = \explode("\n", $content); + $lines = \explode(separator: "\n", string: $content); - $this->output->writeln(' ' . Style::property('Content:')); + $this->output->writeln(' ' . Style::property(text: 'Content:')); // Show first 10 lines or all if less - $displayLines = \array_slice($lines, 0, 10); + $displayLines = \array_slice(array: $lines, offset: 0, length: 10); foreach ($displayLines as $line) { - $this->output->writeln(' ' . Style::muted($line)); + $this->output->writeln(' ' . Style::muted(text: $line)); } // Show truncation indicator if there are more lines - if (\count($lines) > 10) { - $this->output->writeln(' ' . Style::muted(\sprintf('... (%d more lines)', \count($lines) - 10))); + if (\count(value: $lines) > 10) { + $this->output->writeln(' ' . Style::muted(text: \sprintf('... (%d more lines)', \count(value: $lines) - 10))); } $this->output->writeln(''); - $this->output->writeln(' ' . Style::property('Statistics:')); - $this->output->writeln(\sprintf(' • Lines: %s', Style::count(\count($lines)))); - $this->output->writeln(\sprintf(' • Characters: %s', Style::count(\strlen($content)))); - $this->output->writeln(\sprintf(' • Words: %s', Style::count(\str_word_count($content)))); + $this->output->writeln(' ' . Style::property(text: 'Statistics:')); + $this->output->writeln(\sprintf(' • Lines: %s', Style::count(count: \count(value: $lines)))); + $this->output->writeln(\sprintf(' • Characters: %s', Style::count(count: \strlen(string: $content)))); + $this->output->writeln(\sprintf(' • Words: %s', Style::count(count: \str_word_count(string: $content)))); } } @@ -245,34 +245,34 @@ private function suggestSimilarPrompts(PromptProviderInterface $promptProvider): $suggestions = []; foreach ($allPrompts as $id => $_prompt) { $similarity = 0; - \similar_text($this->promptId, $id, $similarity); + \similar_text(string1: $this->promptId, string2: $id, percent: $similarity); if ($similarity > 30) { // 30% similarity threshold $suggestions[] = ['id' => $id, 'similarity' => $similarity]; } } // Sort by similarity - \usort($suggestions, static fn($a, $b) => $b['similarity'] <=> $a['similarity']); + \usort(array: $suggestions, callback: static fn($a, $b) => $b['similarity'] <=> $a['similarity']); if (!empty($suggestions)) { $this->output->writeln(''); $this->output->writeln('Did you mean one of these?'); - foreach (\array_slice($suggestions, 0, 3) as $suggestion) { - $this->output->writeln(\sprintf(' • %s', Style::value($suggestion['id']))); + foreach (\array_slice(array: $suggestions, offset: 0, length: 3) as $suggestion) { + $this->output->writeln(\sprintf(' • %s', Style::value(text: $suggestion['id']))); } } else { $this->output->writeln(''); $this->output->writeln('Available prompts:'); - $promptIds = \array_keys($allPrompts); - \sort($promptIds); - foreach (\array_slice($promptIds, 0, 5) as $id) { - $this->output->writeln(\sprintf(' • %s', Style::value($id))); + $promptIds = \array_keys(array: $allPrompts); + \sort(array: $promptIds); + foreach (\array_slice(array: $promptIds, offset: 0, length: 5) as $id) { + $this->output->writeln(\sprintf(' • %s', Style::value(text: $id))); } - if (\count($promptIds) > 5) { - $this->output->writeln(\sprintf(' ... and %d more', \count($promptIds) - 5)); + if (\count(value: $promptIds) > 5) { + $this->output->writeln(\sprintf(' ... and %d more', \count(value: $promptIds) - 5)); $this->output->writeln(''); - $this->output->writeln('Use ' . Style::command('prompts:list') . ' to see all available prompts.'); + $this->output->writeln('Use ' . Style::command(text: 'prompts:list') . ' to see all available prompts.'); } } } @@ -283,8 +283,8 @@ private function suggestSimilarPrompts(PromptProviderInterface $promptProvider): private function formatPromptType(PromptType $type): string { return match ($type) { - PromptType::Prompt => Style::success('Prompt'), - PromptType::Template => Style::info('Template'), + PromptType::Prompt => Style::success(text: 'Prompt'), + PromptType::Template => Style::info(text: 'Template'), }; } } diff --git a/src/McpServer/Tool/Console/ToolListCommand.php b/src/McpServer/Tool/Console/ToolListCommand.php index 4c21d09d..728c8e02 100644 --- a/src/McpServer/Tool/Console/ToolListCommand.php +++ b/src/McpServer/Tool/Console/ToolListCommand.php @@ -74,7 +74,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int // Get the appropriate loader based on options provided if ($this->configPath !== null) { $this->logger->info(\sprintf('Loading configuration from %s...', $this->configPath)); - $loader = $configProvider->fromPath($this->configPath); + $loader = $configProvider->fromPath(configPath: $this->configPath); } else { $this->logger->info('Loading configuration from default location...'); $loader = $configProvider->fromDefaultLocation(); @@ -100,7 +100,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int $filteredTools = []; foreach ($tools as $tool) { // Filter by ID if specified - if (!empty($this->toolIds) && !\in_array($tool->id, $this->toolIds, true)) { + if (!empty($this->toolIds) && !\in_array(needle: $tool->id, haystack: $this->toolIds, strict: true)) { continue; } @@ -120,7 +120,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int } // Display tools as a table - return $this->displayAsTable($tools); + return $this->displayAsTable(tools: $tools); }, ); } @@ -135,42 +135,42 @@ private function displayAsTable(array $tools): int $title = 'Available Tools'; $this->output->title($title); - $table = new Table($this->output); + $table = new Table(output: $this->output); if ($this->detailed) { - $table->setHeaders(['ID', 'Type', 'Description', 'Schema', 'Commands']); + $table->setHeaders(headers: ['ID', 'Type', 'Description', 'Schema', 'Commands']); } else { - $table->setHeaders(['ID', 'Type', 'Description', 'Schema']); + $table->setHeaders(headers: ['ID', 'Type', 'Description', 'Schema']); } foreach ($tools as $tool) { $hasSchema = $tool->schema !== null && !empty($tool->schema->getProperties()); $row = [ - new TableCell($tool->id, ['style' => new TableCellStyle(['fg' => 'cyan'])]), + new TableCell(value: $tool->id, options: ['style' => new TableCellStyle(options: ['fg' => 'cyan'])]), new TableCell( - $tool->type, - ['style' => new TableCellStyle(['fg' => $tool->type === 'run' ? 'green' : 'blue'])], + value: $tool->type, + options: ['style' => new TableCellStyle(options: ['fg' => $tool->type === 'run' ? 'green' : 'blue'])], ), $tool->description, $hasSchema ? '✓' : '-', ]; if ($this->detailed) { - $commandDetails = $this->formatCommands($tool); + $commandDetails = $this->formatCommands(tool: $tool); $row[] = $commandDetails; } - $table->addRow($row); + $table->addRow(row: $row); if ($this->detailed) { - $table->addRow(new TableSeparator()); + $table->addRow(row: new TableSeparator()); } } $table->render(); $this->output->writeln(''); - $this->output->writeln(\sprintf('%s: %s', Style::property('Total tools'), Style::count(\count($tools)))); + $this->output->writeln(\sprintf('%s: %s', Style::property(text: 'Total tools'), Style::count(count: \count(value: $tools)))); $this->output->writeln(''); $this->output->writeln('To execute a tool, run: tool:run '); @@ -195,12 +195,12 @@ private function formatCommands(ToolDefinition $tool): string $cmdInfo = $command->cmd; if (!empty($args)) { - $cmdInfo .= ' ' . \implode(' ', $args); + $cmdInfo .= ' ' . \implode(separator: ' ', array: $args); } $commands[] = \sprintf('#%d: %s', $index + 1, $cmdInfo); } - return \implode("\n", $commands); + return \implode(separator: "\n", array: $commands); } } diff --git a/src/McpServer/Tool/Console/ToolRunCommand.php b/src/McpServer/Tool/Console/ToolRunCommand.php index 8a9bb1f2..7bb7a504 100644 --- a/src/McpServer/Tool/Console/ToolRunCommand.php +++ b/src/McpServer/Tool/Console/ToolRunCommand.php @@ -78,7 +78,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int // Get the appropriate loader based on options provided if ($this->configPath !== null) { $this->logger->info(\sprintf('Loading configuration from %s...', $this->configPath)); - $loader = $configProvider->fromPath($this->configPath); + $loader = $configProvider->fromPath(configPath: $this->configPath); } else { $this->logger->info('Loading configuration from default location...'); $loader = $configProvider->fromDefaultLocation(); @@ -102,7 +102,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int bindings: [ DirectoriesInterface::class => $dirs, ConfigLoaderInterface::class => $loader, - CommandExecutorInterface::class => $container->make(CommandExecutor::class, [ + CommandExecutorInterface::class => $container->make(alias: CommandExecutor::class, parameters: [ 'projectRoot' => (string) $dirs->getRootPath(), ]), ], @@ -112,11 +112,11 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int ToolProviderInterface $toolProvider, ): int { $toolId = $this->toolId; - $providedArgs = $this->parseProvidedArguments($this->argOptions); + $providedArgs = $this->parseProvidedArguments(inputArgs: $this->argOptions); // If no tool ID is provided, list available tools and prompt for selection if (empty($toolId) && $this->input->isInteractive()) { - $tool = $this->selectTool($toolProvider); + $tool = $this->selectTool(toolProvider: $toolProvider); if (!$tool) { return Command::FAILURE; } @@ -133,7 +133,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int } // Get tool handler - $handler = $handlerFactory->createHandlerForTool($tool); + $handler = $handlerFactory->createHandlerForTool(tool: $tool); // Get arguments for tool execution $args = []; @@ -142,14 +142,14 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int if (!$this->input->isInteractive()) { // In non-interactive mode, validate the provided arguments try { - $args = $this->validateArguments($tool->schema, $providedArgs); + $args = $this->validateArguments(schema: $tool->schema, args: $providedArgs); } catch (\InvalidArgumentException $e) { $this->output->error($e->getMessage()); return Command::FAILURE; } } else { // In interactive mode, prompt for arguments - $args = $this->promptForArguments($tool, $providedArgs); + $args = $this->promptForArguments(tool: $tool, providedArgs: $providedArgs); } } @@ -157,13 +157,13 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int $this->output->writeln(\sprintf('Executing tool "%s"...', $tool->id)); try { - $startTime = \microtime(true); + $startTime = \microtime(as_float: true); // Create progress indicator $progressBar = null; if (!$this->output->isVerbose()) { - $progressBar = new ProgressBar($this->output); - $progressBar->setFormat(' %percent:3s%% [%bar%] %elapsed:6s%'); + $progressBar = new ProgressBar(output: $this->output); + $progressBar->setFormat(format: ' %percent:3s%% [%bar%] %elapsed:6s%'); $progressBar->start(); $progressBar->display(); } @@ -171,7 +171,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int // Execute the tool $result = $handler->execute($tool, $args); - $executionTime = \microtime(true) - $startTime; + $executionTime = \microtime(as_float: true) - $startTime; // Finish progress bar if it was started if ($progressBar !== null) { @@ -180,7 +180,7 @@ public function __invoke(Container $container, DirectoriesInterface $dirs): int } // Display results - $this->displayResults($tool, $result, $executionTime); + $this->displayResults(tool: $tool, result: $result, executionTime: $executionTime); return isset($result['success']) && $result['success'] === false ? Command::FAILURE : Command::SUCCESS; } catch (\Throwable $e) { @@ -221,7 +221,7 @@ private function selectTool(ToolProviderInterface $toolProvider): ?ToolDefinitio $toolMap[$label] = $tool; } - $selectedLabel = $this->choiceQuestion('Select a tool to execute:', $choices); + $selectedLabel = $this->choiceQuestion(question: 'Select a tool to execute:', choices: $choices); return $toolMap[$selectedLabel]; } @@ -247,8 +247,8 @@ private function promptForArguments(ToolDefinition $tool, array $providedArgs): continue; } - $isRequired = \in_array($name, $requiredProps, true); - $default = $schema->getDefaultValue($name); + $isRequired = \in_array(needle: $name, haystack: $requiredProps, strict: true); + $default = $schema->getDefaultValue(propertyName: $name); $type = $propDef['type'] ?? 'string'; $title = $propDef['title'] ?? $name; @@ -269,13 +269,13 @@ private function promptForArguments(ToolDefinition $tool, array $providedArgs): $isRequired ? ', required' : '', ); - $question = new Question('Provide value', $default); + $question = new Question(question: 'Provide value', default: $default); // Add validator based on type - $question->setValidator(static function ($value) use ($name, $type, $isRequired) { + $question->setValidator(validator: static function ($value) use ($name, $type, $isRequired) { if ($value === null || $value === '') { if ($isRequired) { - throw new \RuntimeException("$name is required"); + throw new \RuntimeException(message: "$name is required"); } return null; } @@ -284,16 +284,16 @@ private function promptForArguments(ToolDefinition $tool, array $providedArgs): switch ($type) { case 'number': case 'integer': - if (!\is_numeric($value)) { - throw new \RuntimeException("$name must be a number"); + if (!\is_numeric(value: $value)) { + throw new \RuntimeException(message: "$name must be a number"); } - if ($type === 'integer' && !\filter_var($value, FILTER_VALIDATE_INT)) { - throw new \RuntimeException("$name must be an integer"); + if ($type === 'integer' && !\filter_var(value: $value, filter: FILTER_VALIDATE_INT)) { + throw new \RuntimeException(message: "$name must be an integer"); } break; case 'boolean': - if (!\in_array(\strtolower((string) $value), ['true', 'false', '1', '0', 'yes', 'no'], true)) { - throw new \RuntimeException("$name must be a boolean (true/false, yes/no, 1/0)"); + if (!\in_array(needle: \strtolower(string: (string) $value), haystack: ['true', 'false', '1', '0', 'yes', 'no'], strict: true)) { + throw new \RuntimeException(message: "$name must be a boolean (true/false, yes/no, 1/0)"); } break; } @@ -304,16 +304,16 @@ private function promptForArguments(ToolDefinition $tool, array $providedArgs): // For boolean type, use confirmation question if ($type === 'boolean') { $defaultBool = $default === 'true' || $default === true || $default === 1 || $default === '1'; - $question = new ConfirmationQuestion($questionText, $defaultBool); + $question = new ConfirmationQuestion(question: $questionText, default: $defaultBool); } // Prompt for input - $helper = $this->getHelper('question'); - \assert($helper instanceof QuestionHelper); - $value = $helper->ask($this->input, $this->output, $question); + $helper = $this->getHelper(name: 'question'); + \assert(assertion: $helper instanceof QuestionHelper); + $value = $helper->ask(input: $this->input, output: $this->output, question: $question); // Handle the value for non-string types - if ($type === 'boolean' && !\is_string($value)) { + if ($type === 'boolean' && !\is_string(value: $value)) { $value = $value ? 'true' : 'false'; } @@ -333,18 +333,18 @@ private function validateArguments(ToolSchema $schema, array $args): array { $required = $schema->getRequiredProperties(); $properties = $schema->getProperties(); - if (\is_object($properties)) { + if (\is_object(value: $properties)) { return []; } // Check all required properties are provided foreach ($required as $prop) { if (!isset($args[$prop])) { - $defaultValue = $schema->getDefaultValue($prop); + $defaultValue = $schema->getDefaultValue(propertyName: $prop); if ($defaultValue !== null) { $args[$prop] = $defaultValue; } else { - throw new \InvalidArgumentException(\sprintf('Required argument "%s" is missing', $prop)); + throw new \InvalidArgumentException(message: \sprintf('Required argument "%s" is missing', $prop)); } } } @@ -359,23 +359,23 @@ private function validateArguments(ToolSchema $schema, array $args): array $type = $properties[$name]['type'] ?? 'string'; switch ($type) { case 'integer': - if (!\filter_var($value, FILTER_VALIDATE_INT)) { + if (!\filter_var(value: $value, filter: FILTER_VALIDATE_INT)) { throw new \InvalidArgumentException( - \sprintf('Argument "%s" must be an integer, got "%s"', $name, $value), + message: \sprintf('Argument "%s" must be an integer, got "%s"', $name, $value), ); } break; case 'number': - if (!\is_numeric($value)) { + if (!\is_numeric(value: $value)) { throw new \InvalidArgumentException( - \sprintf('Argument "%s" must be a number, got "%s"', $name, $value), + message: \sprintf('Argument "%s" must be a number, got "%s"', $name, $value), ); } break; case 'boolean': - if (!\in_array(\strtolower((string) $value), ['true', 'false', '1', '0', 'yes', 'no'], true)) { + if (!\in_array(needle: \strtolower(string: (string) $value), haystack: ['true', 'false', '1', '0', 'yes', 'no'], strict: true)) { throw new \InvalidArgumentException( - \sprintf('Argument "%s" must be a boolean, got "%s"', $name, $value), + message: \sprintf('Argument "%s" must be a boolean, got "%s"', $name, $value), ); } break; @@ -393,13 +393,13 @@ private function parseProvidedArguments(array $inputArgs): array $args = []; foreach ($inputArgs as $arg) { - if (!\str_contains((string) $arg, '=')) { + if (!\str_contains(haystack: (string) $arg, needle: '=')) { $this->output->warning(\sprintf('Invalid argument format: %s (expected name=value)', $arg)); continue; } - [$name, $value] = \explode('=', (string) $arg, 2); - $args[\trim($name)] = \trim($value); + [$name, $value] = \explode(separator: '=', string: (string) $arg, limit: 2); + $args[\trim(string: $name)] = \trim(string: $value); } return $args; @@ -413,9 +413,9 @@ private function displayResults(ToolDefinition $tool, array $result, float $exec $this->output->writeln(\sprintf('Tool execution completed in %.2f seconds', $executionTime)); if ($tool->type === 'run') { - $this->displayRunResults($result); + $this->displayRunResults(result: $result); } elseif ($tool->type === 'http') { - $this->displayHttpResults($result); + $this->displayHttpResults(result: $result); } else { // Generic display for any tool type $this->output->writeln('Result:'); @@ -423,7 +423,7 @@ private function displayResults(ToolDefinition $tool, array $result, float $exec if (!empty($result['output'])) { $this->output->writeln($result['output']); } else { - $this->output->writeln(\json_encode($result, JSON_PRETTY_PRINT)); + $this->output->writeln(\json_encode(value: $result, flags: JSON_PRETTY_PRINT)); } } } @@ -443,7 +443,7 @@ private function displayRunResults(array $result): void $this->newLine(); - if (isset($result['commands']) && \is_array($result['commands'])) { + if (isset($result['commands']) && \is_array(value: $result['commands'])) { foreach ($result['commands'] as $i => $cmdResult) { $cmdSuccess = $cmdResult['success'] ?? true; @@ -483,9 +483,9 @@ private function displayHttpResults(array $result): void $outputData = $result['output']; // Try to parse JSON output - $jsonData = \json_decode($outputData, true); + $jsonData = \json_decode(json: $outputData, associative: true); - if (\json_last_error() === JSON_ERROR_NONE && \is_array($jsonData)) { + if (\json_last_error() === JSON_ERROR_NONE && \is_array(value: $jsonData)) { foreach ($jsonData as $i => $response) { $success = $response['success'] ?? false; @@ -505,7 +505,7 @@ private function displayHttpResults(array $result): void if (isset($response['response'])) { $this->output->writeln('Response data:'); - $this->output->writeln(\json_encode($response['response'], JSON_PRETTY_PRINT)); + $this->output->writeln(\json_encode(value: $response['response'], flags: JSON_PRETTY_PRINT)); } $this->output->writeln(''); diff --git a/src/Modifier/Alias/ModifierAliasesParserPlugin.php b/src/Modifier/Alias/ModifierAliasesParserPlugin.php index 85714ede..1c1fde6b 100644 --- a/src/Modifier/Alias/ModifierAliasesParserPlugin.php +++ b/src/Modifier/Alias/ModifierAliasesParserPlugin.php @@ -25,7 +25,7 @@ public function getConfigKey(): string public function supports(array $config): bool { return isset($config['settings']['modifiers']) - && \is_array($config['settings']['modifiers']); + && \is_array(value: $config['settings']['modifiers']); } public function updateConfig(array $config, string $rootPath): array @@ -36,15 +36,15 @@ public function updateConfig(array $config, string $rootPath): array public function parse(array $config, string $rootPath): ?RegistryInterface { - if (!$this->supports($config)) { + if (!$this->supports(config: $config)) { return null; } $modifiersConfig = $config['settings']['modifiers']; foreach ($modifiersConfig as $alias => $modifierConfig) { - $modifier = Modifier::from($modifierConfig); - $this->aliasesRegistry->register($alias, $modifier); + $modifier = Modifier::from(data: $modifierConfig); + $this->aliasesRegistry->register(alias: $alias, modifier: $modifier); } return null; diff --git a/src/Modifier/Alias/ModifierResolver.php b/src/Modifier/Alias/ModifierResolver.php index 87544f71..1e53085d 100644 --- a/src/Modifier/Alias/ModifierResolver.php +++ b/src/Modifier/Alias/ModifierResolver.php @@ -28,10 +28,10 @@ public function resolve(string|array|Modifier $reference): Modifier } // If it's a string, check if it's an alias - if (\is_string($reference)) { - if ($this->aliasesRegistry->has($reference)) { - $modifier = $this->aliasesRegistry->get($reference); - \assert($modifier !== null); + if (\is_string(value: $reference)) { + if ($this->aliasesRegistry->has(alias: $reference)) { + $modifier = $this->aliasesRegistry->get(alias: $reference); + \assert(assertion: $modifier !== null); return $modifier; } @@ -40,7 +40,7 @@ public function resolve(string|array|Modifier $reference): Modifier } // Otherwise, it's an array configuration - return Modifier::from($reference); + return Modifier::from(data: $reference); } /** @@ -52,8 +52,8 @@ public function resolve(string|array|Modifier $reference): Modifier public function resolveAll(array $references): array { return \array_map( - fn($reference) => $this->resolve($reference), - $references, + callback: fn($reference) => $this->resolve(reference: $reference), + array: $references, ); } } diff --git a/src/Modifier/Modifier.php b/src/Modifier/Modifier.php index 2bf0f36d..ccd9fcbf 100644 --- a/src/Modifier/Modifier.php +++ b/src/Modifier/Modifier.php @@ -38,7 +38,7 @@ public static function from(string|array|self $data): self } // If string, treat as modifier name with empty context - if (\is_string($data)) { + if (\is_string(value: $data)) { return new self(name: $data); } @@ -51,7 +51,7 @@ public static function from(string|array|self $data): self } throw new \InvalidArgumentException( - 'Invalid modifier format. Expected string, array with "name" key, or ModifierDto instance.', + message: 'Invalid modifier format. Expected string, array with "name" key, or ModifierDto instance.', ); } @@ -73,6 +73,6 @@ public function jsonSerialize(): array public function __toString(): string { - return \json_encode($this->jsonSerialize(), JSON_THROW_ON_ERROR); + return \json_encode(value: $this->jsonSerialize(), flags: JSON_THROW_ON_ERROR); } } diff --git a/src/Modifier/ModifierBootloader.php b/src/Modifier/ModifierBootloader.php index 5d3c2759..bc8d1f0d 100644 --- a/src/Modifier/ModifierBootloader.php +++ b/src/Modifier/ModifierBootloader.php @@ -22,6 +22,6 @@ public function boot( ConfigLoaderBootloader $parserRegistry, ModifierAliasesParserPlugin $plugin, ): void { - $parserRegistry->registerParserPlugin($plugin); + $parserRegistry->registerParserPlugin(plugin: $plugin); } } diff --git a/src/Modifier/ModifiersApplier.php b/src/Modifier/ModifiersApplier.php index ee39bc9e..b69b46df 100644 --- a/src/Modifier/ModifiersApplier.php +++ b/src/Modifier/ModifiersApplier.php @@ -50,21 +50,21 @@ public function apply(string $content, string $filename): string $this->logger->debug('Applying modifiers to content', [ 'contentType' => $filename, - 'modifierCount' => \count($this->modifiers), + 'modifierCount' => \count(value: $this->modifiers), ]); - $originalLength = \strlen($content); + $originalLength = \strlen(string: $content); $modifiedContent = $content; foreach ($this->modifiers as $modifierId) { - if (!$this->registry->has($modifierId)) { + if (!$this->registry->has(identifier: $modifierId)) { $this->logger->warning('Modifier not found', [ 'modifierId' => (string) $modifierId, ]); continue; } - $modifier = $this->registry->get($modifierId); + $modifier = $this->registry->get(identifier: $modifierId); if (!$modifier->supports($filename)) { $this->logger->debug('Modifier not applicable to content type', [ 'modifierId' => (string) $modifierId, @@ -85,7 +85,7 @@ public function apply(string $content, string $filename): string 'modifierId' => (string) $modifierId, 'contentType' => $filename, 'beforeLength' => $originalLength, - 'afterLength' => \strlen($modifiedContent), + 'afterLength' => \strlen(string: $modifiedContent), ]); } diff --git a/src/Modifier/PhpContentFilter/PhpContentFilter.php b/src/Modifier/PhpContentFilter/PhpContentFilter.php index bcaf9f84..c7bb0f2b 100644 --- a/src/Modifier/PhpContentFilter/PhpContentFilter.php +++ b/src/Modifier/PhpContentFilter/PhpContentFilter.php @@ -89,7 +89,7 @@ public function getIdentifier(): string */ public function supports(string $contentType): bool { - return \str_ends_with($contentType, '.php'); + return \str_ends_with(haystack: $contentType, needle: '.php'); } /** @@ -104,7 +104,7 @@ public function modify(string $content, array $context = []): string $this->config = \array_merge($this->config, $context); try { - $file = PhpFile::fromCode($content); + $file = PhpFile::fromCode(code: $content); $output = ''; foreach ($file->getNamespaces() as $namespace) { @@ -123,7 +123,7 @@ public function modify(string $content, array $context = []): string } foreach ($namespace->getClasses() as $class) { - $output .= $this->processClass($class); + $output .= $this->processClass(class: $class); } } @@ -140,14 +140,14 @@ private function processClass(ClassLike $class): string { // Determine class type and process accordingly if ($class->isInterface()) { - return $this->processInterface($class); + return $this->processInterface(interface: $class); } elseif ($class->isTrait()) { - return $this->processTrait($class); - } elseif (\PHP_VERSION_ID >= 80100 && \method_exists($class, 'isEnum') && $class->isEnum()) { - return $this->processEnum($class); + return $this->processTrait(trait: $class); + } elseif (\PHP_VERSION_ID >= 80100 && \method_exists(object_or_class: $class, method: 'isEnum') && $class->isEnum()) { + return $this->processEnum(enum: $class); } - return $this->processStandardClass($class); + return $this->processStandardClass(class: $class); } /** @@ -156,13 +156,13 @@ private function processClass(ClassLike $class): string private function processStandardClass(ClassType $class): string { // Filter properties - $this->filterProperties($class); + $this->filterProperties(class: $class); // Filter constants - $this->filterConstants($class); + $this->filterConstants(class: $class); // Filter methods - $this->filterMethods($class); + $this->filterMethods(class: $class); // Generate the class code return (string) $class . "\n"; @@ -174,10 +174,10 @@ private function processStandardClass(ClassType $class): string private function processInterface(InterfaceType $interface): string { // Filter constants - $this->filterConstants($interface); + $this->filterConstants(class: $interface); // Filter methods - $this->filterMethods($interface); + $this->filterMethods(class: $interface); // Generate the interface code return (string) $interface . "\n"; @@ -189,13 +189,13 @@ private function processInterface(InterfaceType $interface): string private function processTrait(TraitType $trait): string { // Filter properties - $this->filterProperties($trait); + $this->filterProperties(class: $trait); // Filter constants - $this->filterConstants($trait); + $this->filterConstants(class: $trait); // Filter methods - $this->filterMethods($trait); + $this->filterMethods(class: $trait); // Generate the trait code return (string) $trait . "\n"; @@ -207,10 +207,10 @@ private function processTrait(TraitType $trait): string private function processEnum(EnumType $enum): string { // Filter constants (for backed enums) - $this->filterConstants($enum); + $this->filterConstants(class: $enum); // Filter methods - $this->filterMethods($enum); + $this->filterMethods(class: $enum); // Generate the enum code return (string) $enum . "\n"; @@ -221,25 +221,25 @@ private function processEnum(EnumType $enum): string */ private function filterProperties(ClassLike $class): void { - if (!\method_exists($class, 'getProperties')) { + if (!\method_exists(object_or_class: $class, method: 'getProperties')) { return; } $propertiesToRemove = []; foreach ($class->getProperties() as $property) { - if (!$this->shouldKeepProperty($property)) { + if (!$this->shouldKeepProperty(property: $property)) { $propertiesToRemove[] = $property->getName(); continue; } // Handle doc comments if needed - if (!$this->config['keep_doc_comments'] && \method_exists($property, 'setComment')) { + if (!$this->config['keep_doc_comments'] && \method_exists(object_or_class: $property, method: 'setComment')) { $property->setComment(''); } // Handle attributes if needed - if (!$this->config['keep_attributes'] && \method_exists($property, 'getAttributes')) { + if (!$this->config['keep_attributes'] && \method_exists(object_or_class: $property, method: 'getAttributes')) { foreach ($property->getAttributes() as $attribute) { /** @psalm-suppress UndefinedMethod */ $property->removeAttribute($attribute->getName()); @@ -259,25 +259,25 @@ private function filterProperties(ClassLike $class): void */ private function filterConstants(ClassLike $class): void { - if (!\method_exists($class, 'getConstants')) { + if (!\method_exists(object_or_class: $class, method: 'getConstants')) { return; } $constantsToRemove = []; foreach ($class->getConstants() as $constant) { - if (!$this->shouldKeepConstant($constant)) { + if (!$this->shouldKeepConstant(constant: $constant)) { $constantsToRemove[] = $constant->getName(); continue; } // Handle doc comments if needed - if (!$this->config['keep_doc_comments'] && \method_exists($constant, 'setComment')) { + if (!$this->config['keep_doc_comments'] && \method_exists(object_or_class: $constant, method: 'setComment')) { $constant->setComment(''); } // Handle attributes if needed - if (!$this->config['keep_attributes'] && \method_exists($constant, 'getAttributes')) { + if (!$this->config['keep_attributes'] && \method_exists(object_or_class: $constant, method: 'getAttributes')) { foreach ($constant->getAttributes() as $attribute) { /** @psalm-suppress UndefinedMethod */ $constant->removeAttribute($attribute->getName()); @@ -297,14 +297,14 @@ private function filterConstants(ClassLike $class): void */ private function filterMethods(ClassLike $class): void { - if (!\method_exists($class, 'getMethods')) { + if (!\method_exists(object_or_class: $class, method: 'getMethods')) { return; } $methodsToRemove = []; foreach ($class->getMethods() as $method) { - if (!$this->shouldKeepMethod($method)) { + if (!$this->shouldKeepMethod(method: $method)) { $methodsToRemove[] = $method->getName(); continue; } @@ -341,7 +341,7 @@ private function shouldKeepProperty(Property $property): bool { // Check visibility $visibility = $property->isPublic() ? 'public' : ($property->isProtected() ? 'protected' : 'private'); - if (!\in_array($visibility, $this->config['property_visibility'], true)) { + if (!\in_array(needle: $visibility, haystack: $this->config['property_visibility'], strict: true)) { return false; } @@ -349,14 +349,14 @@ private function shouldKeepProperty(Property $property): bool // If include list is provided and not empty, check against it if (!empty($this->config['include_properties'])) { - if (\in_array($propertyName, $this->config['include_properties'], true)) { + if (\in_array(needle: $propertyName, haystack: $this->config['include_properties'], strict: true)) { return true; } // If we have an include list but the property isn't in it, // still check pattern matches if configured if ($this->config['include_properties_pattern'] !== null) { - if (\preg_match($this->config['include_properties_pattern'], $propertyName)) { + if (\preg_match(pattern: $this->config['include_properties_pattern'], subject: $propertyName)) { return true; } } @@ -366,20 +366,20 @@ private function shouldKeepProperty(Property $property): bool } // Check exclude list - if (\in_array($propertyName, $this->config['exclude_properties'], true)) { + if (\in_array(needle: $propertyName, haystack: $this->config['exclude_properties'], strict: true)) { return false; } // Check exclude pattern if ($this->config['exclude_properties_pattern'] !== null) { - if (\preg_match($this->config['exclude_properties_pattern'], $propertyName)) { + if (\preg_match(pattern: $this->config['exclude_properties_pattern'], subject: $propertyName)) { return false; } } // Check include pattern (when no explicit include list exists) if (empty($this->config['include_properties']) && $this->config['include_properties_pattern'] !== null) { - return (bool) \preg_match($this->config['include_properties_pattern'], $propertyName); + return (bool) \preg_match(pattern: $this->config['include_properties_pattern'], subject: $propertyName); } // No filters matched, keep the property @@ -392,9 +392,9 @@ private function shouldKeepProperty(Property $property): bool private function shouldKeepConstant(Constant $constant): bool { // Check visibility if applicable - if (\method_exists($constant, 'isPublic')) { + if (\method_exists(object_or_class: $constant, method: 'isPublic')) { $visibility = $constant->isPublic() ? 'public' : ($constant->isProtected() ? 'protected' : 'private'); - if (!\in_array($visibility, $this->config['constant_visibility'], true)) { + if (!\in_array(needle: $visibility, haystack: $this->config['constant_visibility'], strict: true)) { return false; } } @@ -403,11 +403,11 @@ private function shouldKeepConstant(Constant $constant): bool // If include list is provided, check against it if (!empty($this->config['include_constants'])) { - return \in_array($constantName, $this->config['include_constants'], true); + return \in_array(needle: $constantName, haystack: $this->config['include_constants'], strict: true); } // Check exclude list - if (\in_array($constantName, $this->config['exclude_constants'], true)) { + if (\in_array(needle: $constantName, haystack: $this->config['exclude_constants'], strict: true)) { return false; } @@ -422,7 +422,7 @@ private function shouldKeepMethod(Method $method): bool { // Check visibility $visibility = $method->isPublic() ? 'public' : ($method->isProtected() ? 'protected' : 'private'); - if (!\in_array($visibility, $this->config['method_visibility'], true)) { + if (!\in_array(needle: $visibility, haystack: $this->config['method_visibility'], strict: true)) { return false; } @@ -430,14 +430,14 @@ private function shouldKeepMethod(Method $method): bool // If include list is provided and not empty, check against it if (!empty($this->config['include_methods'])) { - if (\in_array($methodName, $this->config['include_methods'], true)) { + if (\in_array(needle: $methodName, haystack: $this->config['include_methods'], strict: true)) { return true; } // If we have an include list but the method isn't in it, // still check pattern matches if configured if ($this->config['include_methods_pattern'] !== null) { - if (\preg_match($this->config['include_methods_pattern'], $methodName)) { + if (\preg_match(pattern: $this->config['include_methods_pattern'], subject: $methodName)) { return true; } } @@ -447,20 +447,20 @@ private function shouldKeepMethod(Method $method): bool } // Check exclude list - if (\in_array($methodName, $this->config['exclude_methods'], true)) { + if (\in_array(needle: $methodName, haystack: $this->config['exclude_methods'], strict: true)) { return false; } // Check exclude pattern if ($this->config['exclude_methods_pattern'] !== null) { - if (\preg_match($this->config['exclude_methods_pattern'], $methodName)) { + if (\preg_match(pattern: $this->config['exclude_methods_pattern'], subject: $methodName)) { return false; } } // Check include pattern (when no explicit include list exists) if (empty($this->config['include_methods']) && $this->config['include_methods_pattern'] !== null) { - return (bool) \preg_match($this->config['include_methods_pattern'], $methodName); + return (bool) \preg_match(pattern: $this->config['include_methods_pattern'], subject: $methodName); } // No filters matched, keep the method diff --git a/src/Modifier/PhpDocs/AstDocTransformer.php b/src/Modifier/PhpDocs/AstDocTransformer.php index eb6acb20..ec7aaa06 100644 --- a/src/Modifier/PhpDocs/AstDocTransformer.php +++ b/src/Modifier/PhpDocs/AstDocTransformer.php @@ -63,7 +63,7 @@ public function getIdentifier(): string public function supports(string $contentType): bool { - return \str_ends_with($contentType, '.php'); + return \str_ends_with(haystack: $contentType, needle: '.php'); } public function modify(string $content, array $context = []): string @@ -72,7 +72,7 @@ public function modify(string $content, array $context = []): string $this->config = \array_merge($this->config, $context); try { - $file = PhpFile::fromCode($content); + $file = PhpFile::fromCode(code: $content); $output = ''; foreach ($file->getNamespaces() as $namespace) { @@ -85,13 +85,13 @@ public function modify(string $content, array $context = []): string // Process the appropriate type if ($class instanceof InterfaceType) { - $output .= $this->processInterface($class, $fullClassName); + $output .= $this->processInterface(interface: $class, fullInterfaceName: $fullClassName); } elseif ($class instanceof TraitType) { - $output .= $this->processTrait($class, $fullClassName); + $output .= $this->processTrait(trait: $class, fullTraitName: $fullClassName); } elseif (PHP_VERSION_ID >= 80100 && $class instanceof EnumType) { - $output .= $this->processEnum($class, $fullClassName); + $output .= $this->processEnum(enum: $class, fullEnumName: $fullClassName); } else { - $output .= $this->processClass($class, $fullClassName); + $output .= $this->processClass(class: $class, fullClassName: $fullClassName); } } } @@ -108,11 +108,11 @@ public function modify(string $content, array $context = []): string private function processClass(ClassType $class, string $fullClassName): string { $headingLevel = $this->config['class_heading_level']; - $output = \str_repeat('#', $headingLevel) . " Class: $fullClassName\n\n"; + $output = \str_repeat(string: '#', times: $headingLevel) . " Class: $fullClassName\n\n"; // Add class docblock if available and enabled if ($this->config['keep_doc_comments'] && $class->getComment()) { - $docComment = $this->formatDocComment($class->getComment()); + $docComment = $this->formatDocComment(docComment: $class->getComment()); $output .= "$docComment\n\n"; } @@ -124,19 +124,19 @@ private function processClass(ClassType $class, string $fullClassName): string } if ($class->getImplements()) { - $implements = \array_map(static fn($i) => "`$i`", $class->getImplements()); - $metadata[] = "**Implements:** " . \implode(', ', $implements); + $implements = \array_map(callback: static fn($i) => "`$i`", array: $class->getImplements()); + $metadata[] = "**Implements:** " . \implode(separator: ', ', array: $implements); } if (!empty($metadata)) { - $output .= \implode("\n", $metadata) . "\n\n"; + $output .= \implode(separator: "\n", array: $metadata) . "\n\n"; } // Process constants if enabled if ($this->config['include_constants'] && !empty($class->getConstants())) { $output .= "## Constants\n\n"; foreach ($class->getConstants() as $constant) { - $output .= $this->processConstant($constant); + $output .= $this->processConstant(constant: $constant); } } @@ -145,7 +145,7 @@ private function processClass(ClassType $class, string $fullClassName): string if (!empty($properties)) { $output .= "## Properties\n\n"; foreach ($properties as $property) { - $output .= $this->processProperty($property); + $output .= $this->processProperty(property: $property); } } @@ -154,7 +154,7 @@ private function processClass(ClassType $class, string $fullClassName): string if (!empty($methods)) { $output .= "## Methods\n\n"; foreach ($methods as $method) { - $output .= $this->processMethod($method); + $output .= $this->processMethod(method: $method); } } @@ -167,25 +167,25 @@ private function processClass(ClassType $class, string $fullClassName): string private function processInterface(InterfaceType $interface, string $fullInterfaceName): string { $headingLevel = $this->config['class_heading_level']; - $output = \str_repeat('#', $headingLevel) . " Interface: $fullInterfaceName\n\n"; + $output = \str_repeat(string: '#', times: $headingLevel) . " Interface: $fullInterfaceName\n\n"; // Add interface docblock if available and enabled if ($this->config['keep_doc_comments'] && $interface->getComment()) { - $docComment = $this->formatDocComment($interface->getComment()); + $docComment = $this->formatDocComment(docComment: $interface->getComment()); $output .= "$docComment\n\n"; } // Process interface metadata if ($interface->getExtends()) { - $extends = \array_map(static fn($e) => "`$e`", $interface->getExtends()); - $output .= "**Extends:** " . \implode(', ', $extends) . "\n\n"; + $extends = \array_map(callback: static fn($e) => "`$e`", array: $interface->getExtends()); + $output .= "**Extends:** " . \implode(separator: ', ', array: $extends) . "\n\n"; } // Process constants if enabled if ($this->config['include_constants'] && !empty($interface->getConstants())) { $output .= "## Constants\n\n"; foreach ($interface->getConstants() as $constant) { - $output .= $this->processConstant($constant); + $output .= $this->processConstant(constant: $constant); } } @@ -194,7 +194,7 @@ private function processInterface(InterfaceType $interface, string $fullInterfac if (!empty($methods)) { $output .= "## Methods\n\n"; foreach ($methods as $method) { - $output .= $this->processMethod($method); + $output .= $this->processMethod(method: $method); } } @@ -207,11 +207,11 @@ private function processInterface(InterfaceType $interface, string $fullInterfac private function processTrait(TraitType $trait, string $fullTraitName): string { $headingLevel = $this->config['class_heading_level']; - $output = \str_repeat('#', $headingLevel) . " Trait: $fullTraitName\n\n"; + $output = \str_repeat(string: '#', times: $headingLevel) . " Trait: $fullTraitName\n\n"; // Add trait docblock if available and enabled if ($this->config['keep_doc_comments'] && $trait->getComment()) { - $docComment = $this->formatDocComment($trait->getComment()); + $docComment = $this->formatDocComment(docComment: $trait->getComment()); $output .= "$docComment\n\n"; } @@ -220,7 +220,7 @@ private function processTrait(TraitType $trait, string $fullTraitName): string if (!empty($properties)) { $output .= "## Properties\n\n"; foreach ($properties as $property) { - $output .= $this->processProperty($property); + $output .= $this->processProperty(property: $property); } } @@ -229,7 +229,7 @@ private function processTrait(TraitType $trait, string $fullTraitName): string if (!empty($methods)) { $output .= "## Methods\n\n"; foreach ($methods as $method) { - $output .= $this->processMethod($method); + $output .= $this->processMethod(method: $method); } } @@ -242,11 +242,11 @@ private function processTrait(TraitType $trait, string $fullTraitName): string private function processEnum(EnumType $enum, string $fullEnumName): string { $headingLevel = $this->config['class_heading_level']; - $output = \str_repeat('#', $headingLevel) . " Enum: $fullEnumName\n\n"; + $output = \str_repeat(string: '#', times: $headingLevel) . " Enum: $fullEnumName\n\n"; // Add enum docblock if available and enabled if ($this->config['keep_doc_comments'] && $enum->getComment()) { - $docComment = $this->formatDocComment($enum->getComment()); + $docComment = $this->formatDocComment(docComment: $enum->getComment()); $output .= "$docComment\n\n"; } @@ -263,7 +263,7 @@ private function processEnum(EnumType $enum, string $fullEnumName): string } if ($this->config['keep_doc_comments'] && $case->getComment()) { - $caseComment = \trim($this->formatDocComment($case->getComment())); + $caseComment = \trim(string: $this->formatDocComment(docComment: $case->getComment())); $output .= " - $caseComment"; } @@ -277,7 +277,7 @@ private function processEnum(EnumType $enum, string $fullEnumName): string if (!empty($methods)) { $output .= "## Methods\n\n"; foreach ($methods as $method) { - $output .= $this->processMethod($method); + $output .= $this->processMethod(method: $method); } } @@ -307,7 +307,7 @@ private function processProperty(Property $property): string // Add readonly flag if available (PHP 8.1+) $readonlyFlag = ''; - if (\method_exists($property, 'isReadonly') && $property->isReadonly()) { + if (\method_exists(object_or_class: $property, method: 'isReadonly') && $property->isReadonly()) { $readonlyFlag = ' readonly'; } @@ -315,7 +315,7 @@ private function processProperty(Property $property): string // Add property docblock if available and enabled if ($this->config['keep_doc_comments'] && $property->getComment()) { - $docComment = $this->formatDocComment($property->getComment()); + $docComment = $this->formatDocComment(docComment: $property->getComment()); $output .= "$docComment\n\n"; } @@ -327,7 +327,7 @@ private function processProperty(Property $property): string // Add default value if available and enabled if ($this->config['include_property_defaults'] && $property->getValue() !== null) { - $defaultValue = \var_export($property->getValue(), true); + $defaultValue = \var_export(value: $property->getValue(), return: true); $output .= "**Default:** `$defaultValue`\n\n"; } @@ -361,12 +361,12 @@ private function processMethod(Method $method): string // Add method docblock if available and enabled if ($this->config['keep_doc_comments'] && $method->getComment()) { - $docComment = $this->formatDocComment($method->getComment()); + $docComment = $this->formatDocComment(docComment: $method->getComment()); $output .= "$docComment\n\n"; // Extract route information if enabled if ($this->config['extract_routes']) { - $routeInfo = $this->extractRouteInfo($method->getComment()); + $routeInfo = $this->extractRouteInfo(docComment: $method->getComment()); if ($routeInfo) { $output .= "**Route:** $routeInfo\n\n"; } @@ -385,7 +385,7 @@ private function processMethod(Method $method): string // Add default value if available if ($param->hasDefaultValue()) { - $defaultValue = \var_export($param->getDefaultValue(), true); + $defaultValue = \var_export(value: $param->getDefaultValue(), return: true); $output .= " = $defaultValue"; } @@ -406,7 +406,7 @@ private function processMethod(Method $method): string $output .= "```{$this->config['code_block_format']}\n$methodCode\n```\n\n"; } else { // Just show the method signature - $signature = $this->getMethodSignature($method); + $signature = $this->getMethodSignature(method: $method); $output .= "```{$this->config['code_block_format']}\n$signature\n```\n\n"; } @@ -424,13 +424,13 @@ private function processConstant($constant): string $output = "### $constName\n\n"; // Add constant docblock if available and enabled - if ($this->config['keep_doc_comments'] && \method_exists($constant, 'getComment') && $constant->getComment()) { - $docComment = $this->formatDocComment($constant->getComment()); + if ($this->config['keep_doc_comments'] && \method_exists(object_or_class: $constant, method: 'getComment') && $constant->getComment()) { + $docComment = $this->formatDocComment(docComment: $constant->getComment()); $output .= "$docComment\n\n"; } // Get constant value - $constValue = \var_export($constant->getValue(), true); + $constValue = \var_export(value: $constant->getValue(), return: true); $output .= "**Value:** `$constValue`\n\n"; return $output; @@ -443,18 +443,18 @@ private function extractRouteInfo(string $docComment): ?string { // Look for Symfony style route annotations if (\preg_match( - '/@Route\s*\(\s*["\']([^"\']+)["\'](?:.*?methods\s*=\s*\{([^}]+)\})?/s', - $docComment, - $matches, + pattern: '/@Route\s*\(\s*["\']([^"\']+)["\'](?:.*?methods\s*=\s*\{([^}]+)\})?/s', + subject: $docComment, + matches: $matches, )) { $path = $matches[1]; - $methods = isset($matches[2]) ? \trim(\str_replace(['"', "'"], '', $matches[2])) : 'GET'; + $methods = isset($matches[2]) ? \trim(string: \str_replace(search: ['"', "'"], replace: '', subject: $matches[2])) : 'GET'; return "`$path` ($methods)"; } // Look for Laravel style route annotations - if (\preg_match('/@(Get|Post|Put|Delete|Patch)\s*\(\s*["\']([^"\']+)["\']/', $docComment, $matches)) { - $method = \strtoupper($matches[1]); + if (\preg_match(pattern: '/@(Get|Post|Put|Delete|Patch)\s*\(\s*["\']([^"\']+)["\']/', subject: $docComment, matches: $matches)) { + $method = \strtoupper(string: $matches[1]); $path = $matches[2]; return "`$path` ($method)"; } @@ -482,14 +482,14 @@ private function getMethodSignature(Method $method): string $paramStr = $paramType . $paramName; if ($param->hasDefaultValue()) { - $defaultValue = \var_export($param->getDefaultValue(), true); + $defaultValue = \var_export(value: $param->getDefaultValue(), return: true); $paramStr .= ' = ' . $defaultValue; } $params[] = $paramStr; } - $paramsStr = \implode(', ', $params); + $paramsStr = \implode(separator: ', ', array: $params); $returnType = $method->getReturnType() ? ': ' . (string) $method->getReturnType() : ''; return "{$visibility}{$staticFlag}{$abstractFlag}{$finalFlag}function {$methodName}({$paramsStr}){$returnType}"; @@ -501,18 +501,18 @@ private function getMethodSignature(Method $method): string private function formatDocComment(string $docComment): string { // Remove comment start and end markers - $docComment = \preg_replace(['#^\s*/\*+#', '#\*+/\s*$#'], '', $docComment); + $docComment = \preg_replace(pattern: ['#^\s*/\*+#', '#\*+/\s*$#'], replacement: '', subject: $docComment); // Split into lines - $lines = \explode("\n", (string) $docComment); + $lines = \explode(separator: "\n", string: (string) $docComment); $result = []; foreach ($lines as $line) { // Remove leading asterisks and whitespace - $line = \preg_replace('#^\s*\*\s?#', '', $line); + $line = \preg_replace(pattern: '#^\s*\*\s?#', replacement: '', subject: $line); // Skip empty lines at the beginning - if (empty($result) && \trim((string) $line) === '') { + if (empty($result) && \trim(string: (string) $line) === '') { continue; } @@ -520,6 +520,6 @@ private function formatDocComment(string $docComment): string } // Join lines back together - return \implode("\n", $result); + return \implode(separator: "\n", array: $result); } } diff --git a/src/Modifier/PhpSignature/PhpSignature.php b/src/Modifier/PhpSignature/PhpSignature.php index 0a69cbce..c277a1b9 100644 --- a/src/Modifier/PhpSignature/PhpSignature.php +++ b/src/Modifier/PhpSignature/PhpSignature.php @@ -32,13 +32,13 @@ public function getIdentifier(): string public function supports(string $contentType): bool { - return \str_ends_with($contentType, '.php'); + return \str_ends_with(haystack: $contentType, needle: '.php'); } public function modify(string $content, array $context = []): string { try { - $file = PhpFile::fromCode($content); + $file = PhpFile::fromCode(code: $content); $output = ''; foreach ($file->getNamespaces() as $namespace) { @@ -49,7 +49,7 @@ public function modify(string $content, array $context = []): string } foreach ($namespace->getClasses() as $class) { - $output .= $this->processClass($class); + $output .= $this->processClass(class: $class); } } @@ -68,13 +68,13 @@ private function processClass(ClassLike $class): string // Determine class type and generate signature if ($class->isInterface()) { - $output .= $this->generateInterfaceSignature($class); + $output .= $this->generateInterfaceSignature(interface: $class); } elseif ($class->isTrait()) { - $output .= $this->generateTraitSignature($class); - } elseif (PHP_VERSION_ID >= 80100 && \method_exists($class, 'isEnum') && $class->isEnum()) { - $output .= $this->generateEnumSignature($class); + $output .= $this->generateTraitSignature(trait: $class); + } elseif (PHP_VERSION_ID >= 80100 && \method_exists(object_or_class: $class, method: 'isEnum') && $class->isEnum()) { + $output .= $this->generateEnumSignature(enum: $class); } else { - $output .= $this->generateClassSignature($class); + $output .= $this->generateClassSignature(class: $class); } return $output . "\n"; @@ -88,14 +88,14 @@ private function generateClassSignature(ClassType $class): string // Remove not public properties foreach ($class->getProperties() as $property) { if (!$property->isPublic()) { - $class->removeProperty($property->getName()); + $class->removeProperty(name: $property->getName()); } } // Remove not public constants foreach ($class->getConstants() as $constant) { if (!$constant->isPublic()) { - $class->removeConstant($constant->getName()); + $class->removeConstant(name: $constant->getName()); } } @@ -103,15 +103,15 @@ private function generateClassSignature(ClassType $class): string // Remove method bodies foreach ($class->getMethods() as $method) { // if is magic method, skip - if (\in_array($method->getName(), self::MAGIC_METHODS, true)) { + if (\in_array(needle: $method->getName(), haystack: self::MAGIC_METHODS, strict: true)) { continue; } if (!$method->isPublic()) { - $class->removeMethod($method->getName()); + $class->removeMethod(name: $method->getName()); } - $method->setBody($method->isAbstract() ? '' : '/* ... */'); + $method->setBody(code: $method->isAbstract() ? '' : '/* ... */'); } // Generate the class code @@ -135,22 +135,22 @@ private function generateTraitSignature(TraitType $trait): string // Remove not public properties foreach ($trait->getProperties() as $property) { if (!$property->isPublic()) { - $trait->removeProperty($property->getName()); + $trait->removeProperty(name: $property->getName()); } } // Remove not public constants foreach ($trait->getConstants() as $constant) { if (!$constant->isPublic()) { - $trait->removeConstant($constant->getName()); + $trait->removeConstant(name: $constant->getName()); } } foreach ($trait->getMethods() as $method) { if (!$method->isPublic()) { - $trait->removeMethod($method->getName()); + $trait->removeMethod(name: $method->getName()); } - $method->setBody('/* ... */'); + $method->setBody(code: '/* ... */'); } // Generate the trait code @@ -165,9 +165,9 @@ private function generateEnumSignature(EnumType $enum): string // Remove method bodies foreach ($enum->getMethods() as $method) { if (!$method->isPublic()) { - $enum->removeMethod($method->getName()); + $enum->removeMethod(name: $method->getName()); } - $method->setBody('/* ... */'); + $method->setBody(code: '/* ... */'); } // Generate the enum code diff --git a/src/Modifier/Sanitizer/Rule/CommentInsertionRule.php b/src/Modifier/Sanitizer/Rule/CommentInsertionRule.php index 0cf8a67b..ae0bf9ce 100644 --- a/src/Modifier/Sanitizer/Rule/CommentInsertionRule.php +++ b/src/Modifier/Sanitizer/Rule/CommentInsertionRule.php @@ -38,44 +38,44 @@ public function apply(string $content): string { // Add file header comment if (!empty($this->fileHeaderComment)) { - $comment = $this->formatPhpComment($this->fileHeaderComment); + $comment = $this->formatPhpComment(comment: $this->fileHeaderComment); $content = $comment . PHP_EOL . PHP_EOL . $content; } // Add class comments if (!empty($this->classComment)) { - $comment = $this->formatPhpComment($this->classComment); + $comment = $this->formatPhpComment(comment: $this->classComment); $content = (string) \preg_replace( - '/(class|interface|trait|enum)\s+([a-zA-Z0-9_]+)/', - PHP_EOL . $comment . PHP_EOL . '$1 $2', - $content, + pattern: '/(class|interface|trait|enum)\s+([a-zA-Z0-9_]+)/', + replacement: PHP_EOL . $comment . PHP_EOL . '$1 $2', + subject: $content, ); } // Add method comments if (!empty($this->methodComment)) { - $comment = $this->formatPhpComment($this->methodComment); + $comment = $this->formatPhpComment(comment: $this->methodComment); $content = (string) \preg_replace( - '/(\s+)public|private|protected\s+function/', - '$1' . PHP_EOL . '$1' . $comment . PHP_EOL . '$1$0', - (string) $content, + pattern: '/(\s+)public|private|protected\s+function/', + replacement: '$1' . PHP_EOL . '$1' . $comment . PHP_EOL . '$1$0', + subject: (string) $content, ); } // Add random comments if ($this->frequency > 0 && !empty($this->randomComments)) { - $lines = \explode(PHP_EOL, (string) $content); + $lines = \explode(separator: PHP_EOL, string: (string) $content); $result = []; foreach ($lines as $i => $line) { $result[] = $line; - if ($i % $this->frequency === 0 && \trim($line) !== '') { + if ($i % $this->frequency === 0 && \trim(string: $line) !== '') { $randomComment = $this->randomComments[\array_rand($this->randomComments)]; $indentation = ''; // Try to detect indentation level - if (\preg_match('/^(\s+)/', $line, $matches)) { + if (\preg_match(pattern: '/^(\s+)/', subject: $line, matches: $matches)) { $indentation = $matches[1]; } @@ -83,7 +83,7 @@ public function apply(string $content): string } } - $content = \implode(PHP_EOL, $result); + $content = \implode(separator: PHP_EOL, array: $result); } return $content; @@ -94,9 +94,9 @@ public function apply(string $content): string */ private function formatPhpComment(string $comment): string { - if (\str_contains($comment, PHP_EOL)) { + if (\str_contains(haystack: $comment, needle: PHP_EOL)) { // Multi-line comment - $lines = \explode(PHP_EOL, $comment); + $lines = \explode(separator: PHP_EOL, string: $comment); $result = "/**" . PHP_EOL; foreach ($lines as $line) { diff --git a/src/Modifier/Sanitizer/Rule/KeywordRemovalRule.php b/src/Modifier/Sanitizer/Rule/KeywordRemovalRule.php index fec9558b..ec30904f 100644 --- a/src/Modifier/Sanitizer/Rule/KeywordRemovalRule.php +++ b/src/Modifier/Sanitizer/Rule/KeywordRemovalRule.php @@ -35,7 +35,7 @@ public function apply(string $content): string return $content; } - $lines = \explode(PHP_EOL, $content); + $lines = \explode(separator: PHP_EOL, string: $content); $result = []; foreach ($lines as $line) { @@ -53,7 +53,7 @@ public function apply(string $content): string if ($matches) { if (!$this->removeLines) { // Replace just the keywords - $line = $this->replaceKeywords($line); + $line = $this->replaceKeywords(line: $line); $result[] = $line; } else { // If removeLines is true, we skip this line entirely @@ -64,7 +64,7 @@ public function apply(string $content): string } } - return \implode(PHP_EOL, $result); + return \implode(separator: PHP_EOL, array: $result); } /** @@ -74,8 +74,8 @@ private function replaceKeywords(string $line): string { foreach ($this->keywords as $keyword) { $line = $this->caseSensitive - ? \str_replace($keyword, $this->replacement, $line) - : (string) \preg_replace('/' . \preg_quote($keyword, '/') . '/i', $this->replacement, $line); + ? \str_replace(search: $keyword, replace: $this->replacement, subject: $line) + : (string) \preg_replace(pattern: '/' . \preg_quote(str: $keyword, delimiter: '/') . '/i', replacement: $this->replacement, subject: $line); } return $line; diff --git a/src/Modifier/Sanitizer/Rule/RegexReplacementRule.php b/src/Modifier/Sanitizer/Rule/RegexReplacementRule.php index eda806cd..812c2030 100644 --- a/src/Modifier/Sanitizer/Rule/RegexReplacementRule.php +++ b/src/Modifier/Sanitizer/Rule/RegexReplacementRule.php @@ -27,7 +27,7 @@ public function apply(string $content): string { foreach ($this->patterns as $pattern => $replacement) { /** @var string $content */ - $content = \preg_replace($pattern, $replacement, $content); + $content = \preg_replace(pattern: $pattern, replacement: $replacement, subject: $content); } return $content; diff --git a/src/Modifier/Sanitizer/Rule/RuleFactory.php b/src/Modifier/Sanitizer/Rule/RuleFactory.php index 4ad4d505..a9ae0b1c 100644 --- a/src/Modifier/Sanitizer/Rule/RuleFactory.php +++ b/src/Modifier/Sanitizer/Rule/RuleFactory.php @@ -15,15 +15,15 @@ final class RuleFactory public function createFromConfig(array $config): RuleInterface { if (!isset($config['type'])) { - throw new \InvalidArgumentException('Rule configuration must include a "type" field'); + throw new \InvalidArgumentException(message: 'Rule configuration must include a "type" field'); } return match ($config['type']) { - 'keyword' => $this->createKeywordRemovalRule($config), - 'regex' => $this->createRegexReplacementRule($config), - 'comment' => $this->createCommentInsertionRule($config), + 'keyword' => $this->createKeywordRemovalRule(config: $config), + 'regex' => $this->createRegexReplacementRule(config: $config), + 'comment' => $this->createCommentInsertionRule(config: $config), default => throw new \InvalidArgumentException( - \sprintf('Unsupported rule type: %s', $config['type']), + message: \sprintf('Unsupported rule type: %s', $config['type']), ), }; } @@ -33,8 +33,8 @@ public function createFromConfig(array $config): RuleInterface */ private function createKeywordRemovalRule(array $config): KeywordRemovalRule { - if (!isset($config['keywords']) || !\is_array($config['keywords'])) { - throw new \InvalidArgumentException('Keyword rule must include a "keywords" array'); + if (!isset($config['keywords']) || !\is_array(value: $config['keywords'])) { + throw new \InvalidArgumentException(message: 'Keyword rule must include a "keywords" array'); } return new KeywordRemovalRule( @@ -53,20 +53,20 @@ private function createRegexReplacementRule(array $config): RegexReplacementRule { $patterns = []; if (isset($config['patterns'])) { - if (!\is_array($config['patterns'])) { - throw new \InvalidArgumentException('Regex rule "patterns" object must be an array'); + if (!\is_array(value: $config['patterns'])) { + throw new \InvalidArgumentException(message: 'Regex rule "patterns" object must be an array'); } $patterns = $config['patterns']; } // Handle predefined pattern aliases if specified - if (isset($config['usePatterns']) && \is_array($config['usePatterns'])) { - $patterns = \array_merge($patterns, $this->getPatternsByAliases($config['usePatterns'])); + if (isset($config['usePatterns']) && \is_array(value: $config['usePatterns'])) { + $patterns = \array_merge($patterns, $this->getPatternsByAliases(aliases: $config['usePatterns'])); } if (empty($patterns)) { - throw new \InvalidArgumentException('Regex rule must include "patterns" or "usePatterns"'); + throw new \InvalidArgumentException(message: 'Regex rule must include "patterns" or "usePatterns"'); } return new RegexReplacementRule( diff --git a/src/Modifier/Sanitizer/SanitizerModifier.php b/src/Modifier/Sanitizer/SanitizerModifier.php index f9637e4c..ef07b582 100644 --- a/src/Modifier/Sanitizer/SanitizerModifier.php +++ b/src/Modifier/Sanitizer/SanitizerModifier.php @@ -54,11 +54,11 @@ public function modify(string $content, array $context = []): string // Apply each rule to the sanitizer foreach ($rules as $ruleConfig) { - $rule = $this->ruleFactory->createFromConfig($ruleConfig); - $sanitizer->addRule($rule); + $rule = $this->ruleFactory->createFromConfig(config: $ruleConfig); + $sanitizer->addRule(rule: $rule); } // Apply sanitization rules to the content - return $sanitizer->sanitize($content); + return $sanitizer->sanitize(content: $content); } } diff --git a/src/Source/BaseSource.php b/src/Source/BaseSource.php index 4d6deecf..7f388bcb 100644 --- a/src/Source/BaseSource.php +++ b/src/Source/BaseSource.php @@ -19,7 +19,7 @@ public function __construct( public function getDescription(): string { - return \trim($this->description); + return \trim(string: $this->description); } public function hasDescription(): bool @@ -29,7 +29,7 @@ public function hasDescription(): bool public function getTags(): array { - return \array_values(\array_unique($this->tags)); + return \array_values(array: \array_unique(array: $this->tags)); } public function hasTags(): bool @@ -46,9 +46,9 @@ public function parseContent( public function jsonSerialize(): array { - return \array_filter([ + return \array_filter(array: [ 'description' => $this->getDescription(), 'tags' => $this->getTags(), - ], static fn($value) => $value !== null && $value !== '' && $value !== []); + ], callback: static fn($value) => $value !== null && $value !== '' && $value !== []); } } diff --git a/src/Source/Composer/ComposerSource.php b/src/Source/Composer/ComposerSource.php index aedcd775..eb77c223 100644 --- a/src/Source/Composer/ComposerSource.php +++ b/src/Source/Composer/ComposerSource.php @@ -103,7 +103,7 @@ public function maxFiles(): int #[\Override] public function jsonSerialize(): array { - return \array_filter([ + return \array_filter(array: [ 'type' => 'composer', ...parent::jsonSerialize(), 'composerPath' => $this->composerPath, @@ -115,6 +115,6 @@ public function jsonSerialize(): array 'notContains' => $this->notContains, 'includeDevDependencies' => $this->includeDevDependencies, 'treeView' => $this->treeView, - ], static fn($value) => $value !== null && $value !== '' && $value !== []); + ], callback: static fn($value) => $value !== null && $value !== '' && $value !== []); } } diff --git a/src/Source/Composer/ComposerSourceBootloader.php b/src/Source/Composer/ComposerSourceBootloader.php index 9cc8d2e8..98e20325 100644 --- a/src/Source/Composer/ComposerSourceBootloader.php +++ b/src/Source/Composer/ComposerSourceBootloader.php @@ -49,7 +49,7 @@ public function init( SourceRegistryInterface $sourceRegistry, ComposerSourceFactory $factory, ): void { - $registry->register(ComposerSourceFetcher::class); + $registry->register(fetcher: ComposerSourceFetcher::class); $sourceRegistry->register($factory); } } diff --git a/src/Source/Composer/ComposerSourceFactory.php b/src/Source/Composer/ComposerSourceFactory.php index e0155ac2..bcfb6c5d 100644 --- a/src/Source/Composer/ComposerSourceFactory.php +++ b/src/Source/Composer/ComposerSourceFactory.php @@ -27,13 +27,13 @@ public function create(array $config): SourceInterface ]); if (isset($config['modifiers'])) { - $config['modifiers'] = $this->parseModifiers($config['modifiers']); + $config['modifiers'] = $this->parseModifiers(modifiersConfig: $config['modifiers']); } $composerPath = $config['composerPath'] ?? '.'; // If the path is relative, make it absolute using the root path - if (!\str_starts_with($composerPath, '/')) { + if (!\str_starts_with(haystack: $composerPath, needle: '/')) { $composerPath = $this->dirs->getRootPath()->join($composerPath); } @@ -47,7 +47,7 @@ public function create(array $config): SourceInterface contains: $config['contains'] ?? [], notContains: $config['notContains'] ?? [], includeDevDependencies: $config['includeDevDependencies'] ?? false, - treeView: TreeViewConfig::fromArray($config), + treeView: TreeViewConfig::fromArray(data: $config), modifiers: $config['modifiers'] ?? [], tags: $config['tags'] ?? [], ); diff --git a/src/Source/Composer/ComposerSourceFetcher.php b/src/Source/Composer/ComposerSourceFetcher.php index edb5a785..00cac693 100644 --- a/src/Source/Composer/ComposerSourceFetcher.php +++ b/src/Source/Composer/ComposerSourceFetcher.php @@ -46,7 +46,7 @@ public function __construct( public function supports(SourceInterface $source): bool { $isSupported = $source instanceof ComposerSource; - $this->logDebug('Checking if source is supported', [ + $this->logDebug(message: 'Checking if source is supported', context: [ 'sourceType' => $source::class, 'isSupported' => $isSupported, ]); @@ -57,15 +57,15 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi { if (!$source instanceof ComposerSource) { $errorMessage = 'Source must be an instance of ComposerSource'; - $this->logError($errorMessage, [ + $this->logError(message: $errorMessage, context: [ 'sourceType' => $source::class, ]); - throw new \InvalidArgumentException($errorMessage); + throw new \InvalidArgumentException(message: $errorMessage); } - $description = $this->variableResolver->resolve($source->getDescription()); + $description = $this->variableResolver->resolve(strings: $source->getDescription()); - $this->logInfo('Fetching Composer source content', [ + $this->logInfo(message: 'Fetching Composer source content', context: [ 'description' => $description, 'composerPath' => $source->composerPath, 'includeDevDependencies' => $source->includeDevDependencies, @@ -74,7 +74,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi // Create a content builder $builder = $this->builderFactory ->create() - ->addTitle($description); + ->addTitle(title: $description); // Get packages from the provider $packages = $this->provider->getPackages( @@ -83,42 +83,42 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi ); // Filter packages if packages is set - $packages = $packages->filter($source->packages); + $packages = $packages->filter(pattern: $source->packages); if ($packages->count() === 0) { - $this->logWarning('No matching packages found', [ + $this->logWarning(message: 'No matching packages found', context: [ 'composerPath' => $source->composerPath, 'packages' => $source->packages, ]); - $builder->addText('No matching packages found.'); + $builder->addText(text: 'No matching packages found.'); return $builder->build(); } - $this->logInfo('Found matching packages', [ + $this->logInfo(message: 'Found matching packages', context: [ 'count' => $packages->count(), - 'packages' => \array_keys($packages->all()), + 'packages' => \array_keys(array: $packages->all()), ]); // Generate a tree view of selected packages if requested if ($source->treeView->enabled) { - $this->logDebug('Generating package tree view'); - $builder->addTreeView($packages->generateTree()); + $this->logDebug(message: 'Generating package tree view'); + $builder->addTreeView(treeView: $packages->generateTree()); } // For each package, fetch its source code foreach ($packages as $package) { - $this->logInfo('Processing package', [ + $this->logInfo(message: 'Processing package', context: [ 'name' => $package->name, 'version' => $package->version, 'path' => $package->path, ]); - $builder->addTitle(\sprintf('%s (%s)', $package->name, $package->version), 2); + $builder->addTitle(title: \sprintf('%s (%s)', $package->name, $package->version), level: 2); // Add package description and metadata if available if ($package->getDescription()) { - $builder->addDescription($package->getDescription()); + $builder->addDescription(description: $package->getDescription()); } // Create a metadata section with authors, license, homepage, etc. @@ -137,12 +137,12 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi } if (!empty($metadata)) { - $builder->addText(\implode("\n", $metadata)); + $builder->addText(text: \implode(separator: "\n", array: $metadata)); } // Get source directories for this package $sourceDirs = $package->getSourceDirectories(); - $this->logDebug('Found source directories', [ + $this->logDebug(message: 'Found source directories', context: [ 'package' => $package->name, 'directories' => $sourceDirs, ]); @@ -150,15 +150,15 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi // For each source directory, create a FileSource and fetch its content foreach ($sourceDirs as $dir) { $sourceDir = $package->path . '/' . $dir; - if (!\is_dir($sourceDir)) { - $this->logWarning('Source directory not found', [ + if (!\is_dir(filename: $sourceDir)) { + $this->logWarning(message: 'Source directory not found', context: [ 'package' => $package->name, 'directory' => $sourceDir, ]); continue; } - $this->logDebug('Creating FileSource for directory', [ + $this->logDebug(message: 'Creating FileSource for directory', context: [ 'package' => $package->name, 'directory' => $sourceDir, ]); @@ -177,17 +177,17 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi // Use the FileSourceFetcher to fetch the content try { - $content = $this->fileSourceFetcher->fetch($fileSource, $modifiersApplier); - $builder->addText($content); + $content = $this->fileSourceFetcher->fetch(source: $fileSource, modifiersApplier: $modifiersApplier); + $builder->addText(text: $content); } catch (\Throwable $e) { - $this->logError('Error fetching package source', [ + $this->logError(message: 'Error fetching package source', context: [ 'package' => $package->name, 'directory' => $sourceDir, 'error' => $e->getMessage(), ]); $builder->addText( - \sprintf( + text: \sprintf( "Error fetching source for %s in directory %s: %s", $package->name, $sourceDir, @@ -201,9 +201,9 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi } $content = $builder->build(); - $this->logInfo('Composer source content fetched successfully', [ + $this->logInfo(message: 'Composer source content fetched successfully', context: [ 'packageCount' => $packages->count(), - 'contentLength' => \strlen($content), + 'contentLength' => \strlen(string: $content), ]); return $content; diff --git a/src/Source/Composer/Package/ComposerPackageCollection.php b/src/Source/Composer/Package/ComposerPackageCollection.php index 9c3fe49c..140165b4 100644 --- a/src/Source/Composer/Package/ComposerPackageCollection.php +++ b/src/Source/Composer/Package/ComposerPackageCollection.php @@ -22,7 +22,7 @@ final class ComposerPackageCollection implements \IteratorAggregate, \ArrayAcces public function __construct(array $packages = []) { foreach ($packages as $package) { - $this->add($package); + $this->add(package: $package); } } @@ -76,7 +76,7 @@ public function filter(string|array $pattern): self foreach ($this->packages as $name => $package) { foreach ($patterns as $pattern) { - if (\fnmatch($pattern, $name)) { + if (\fnmatch(pattern: $pattern, filename: $name)) { $filtered[$name] = $package; break; } @@ -103,7 +103,7 @@ public function all(): array */ public function getIterator(): \Traversable { - return new \ArrayIterator($this->packages); + return new \ArrayIterator(array: $this->packages); } /** @@ -129,7 +129,7 @@ public function offsetSet(mixed $offset, mixed $value): void { if (!$value instanceof ComposerPackageInfo) { throw new \InvalidArgumentException( - \sprintf('Value must be an instance of %s', ComposerPackageInfo::class), + message: \sprintf('Value must be an instance of %s', ComposerPackageInfo::class), ); } @@ -149,7 +149,7 @@ public function offsetUnset(mixed $offset): void */ public function count(): int { - return \count($this->packages); + return \count(value: $this->packages); } /** @@ -169,15 +169,15 @@ public function generateTree(): string // Add description if available if ($description = $package->getDescription()) { // Truncate long descriptions - if (\strlen($description) > 60) { - $description = \substr($description, 0, 57) . '...'; + if (\strlen(string: $description) > 60) { + $description = \substr(string: $description, offset: 0, length: 57) . '...'; } $tree .= "│ └── {$description}\n"; } // Add source directories if available $sourceDirs = $package->getSourceDirectories(); - $lastSourceDirIndex = \count($sourceDirs) - 1; + $lastSourceDirIndex = \count(value: $sourceDirs) - 1; foreach ($sourceDirs as $index => $dir) { $isLast = $index === $lastSourceDirIndex; @@ -191,10 +191,10 @@ public function generateTree(): string public function jsonSerialize(): array { - return \array_map(static fn($package) => [ + return \array_map(callback: static fn($package) => [ 'version' => $package->version, 'description' => $package->getDescription(), 'path' => $package->path, - ], $this->packages); + ], array: $this->packages); } } diff --git a/src/Source/Composer/Package/ComposerPackageInfo.php b/src/Source/Composer/Package/ComposerPackageInfo.php index c4ffc70f..1a43bd7e 100644 --- a/src/Source/Composer/Package/ComposerPackageInfo.php +++ b/src/Source/Composer/Package/ComposerPackageInfo.php @@ -61,11 +61,11 @@ public function getFormattedAuthors(): string } if (!empty($authorParts)) { - $formattedAuthors[] = \implode(' ', $authorParts); + $formattedAuthors[] = \implode(separator: ' ', array: $authorParts); } } - return \implode(', ', $formattedAuthors); + return \implode(separator: ', ', array: $formattedAuthors); } /** @@ -83,8 +83,8 @@ public function getFormattedLicense(): string { $license = $this->getLicense(); - if (\is_array($license)) { - return \implode(', ', $license); + if (\is_array(value: $license)) { + return \implode(separator: ', ', array: $license); } return $license; @@ -109,7 +109,7 @@ public function getSourceDirectories(): array $psr4Dirs = []; if (isset($this->composerConfig['autoload']['psr-4'])) { foreach ($this->composerConfig['autoload']['psr-4'] as $dirs) { - if (\is_array($dirs)) { + if (\is_array(value: $dirs)) { foreach ($dirs as $dir) { $psr4Dirs[] = $dir; } @@ -121,14 +121,14 @@ public function getSourceDirectories(): array // If we have PSR-4 directories, return them if (!empty($psr4Dirs)) { - return \array_unique($psr4Dirs); + return \array_unique(array: $psr4Dirs); } // Check PSR-0 autoload configuration as fallback $psr0Dirs = []; if (isset($this->composerConfig['autoload']['psr-0'])) { foreach ($this->composerConfig['autoload']['psr-0'] as $dirs) { - if (\is_array($dirs)) { + if (\is_array(value: $dirs)) { foreach ($dirs as $dir) { $psr0Dirs[] = $dir; } @@ -140,16 +140,16 @@ public function getSourceDirectories(): array // If we have PSR-0 directories, return them if (!empty($psr0Dirs)) { - return \array_unique($psr0Dirs); + return \array_unique(array: $psr0Dirs); } // Check classmap autoload configuration as fallback $classmapDirs = []; if (isset($this->composerConfig['autoload']['classmap']) - && \is_array($this->composerConfig['autoload']['classmap']) + && \is_array(value: $this->composerConfig['autoload']['classmap']) ) { foreach ($this->composerConfig['autoload']['classmap'] as $dir) { - if (\is_string($dir)) { + if (\is_string(value: $dir)) { $classmapDirs[] = $dir; } } @@ -157,13 +157,13 @@ public function getSourceDirectories(): array // If we have classmap directories, return them if (!empty($classmapDirs)) { - return \array_unique($classmapDirs); + return \array_unique(array: $classmapDirs); } // Fallback to common source directories $commonDirs = ['src', 'lib', 'library']; foreach ($commonDirs as $dir) { - if (\is_dir($this->path . '/' . $dir)) { + if (\is_dir(filename: $this->path . '/' . $dir)) { return [$dir]; } } @@ -192,7 +192,7 @@ public function getFormattedKeywords(): string return ''; } - return \implode(', ', $keywords); + return \implode(separator: ', ', array: $keywords); } /** @@ -209,7 +209,7 @@ public function getType(): string public function isAbandoned(): bool { return isset($this->composerConfig['abandoned']) && - ($this->composerConfig['abandoned'] === true || \is_string($this->composerConfig['abandoned'])); + ($this->composerConfig['abandoned'] === true || \is_string(value: $this->composerConfig['abandoned'])); } /** @@ -217,7 +217,7 @@ public function isAbandoned(): bool */ public function getReplacementPackage(): ?string { - if ($this->isAbandoned() && \is_string($this->composerConfig['abandoned'])) { + if ($this->isAbandoned() && \is_string(value: $this->composerConfig['abandoned'])) { return $this->composerConfig['abandoned']; } @@ -270,6 +270,6 @@ public function getFormattedSupport(): string $result[] = "IRC: {$support['irc']}"; } - return \implode("\n", $result); + return \implode(separator: "\n", array: $result); } } diff --git a/src/Source/Composer/Provider/AbstractComposerProvider.php b/src/Source/Composer/Provider/AbstractComposerProvider.php index 5d58926a..4e09908a 100644 --- a/src/Source/Composer/Provider/AbstractComposerProvider.php +++ b/src/Source/Composer/Provider/AbstractComposerProvider.php @@ -34,9 +34,9 @@ protected function extractPackageVersionsFromLock(?array $lockData, bool $includ $versions = []; // Process regular packages - if (isset($lockData['packages']) && \is_array($lockData['packages'])) { + if (isset($lockData['packages']) && \is_array(value: $lockData['packages'])) { foreach ($lockData['packages'] as $package) { - if (!isset($package['name']) || !\is_string($package['name'])) { + if (!isset($package['name']) || !\is_string(value: $package['name'])) { continue; } @@ -50,9 +50,9 @@ protected function extractPackageVersionsFromLock(?array $lockData, bool $includ } // Process dev packages if requested - if ($includeDevDependencies && isset($lockData['packages-dev']) && \is_array($lockData['packages-dev'])) { + if ($includeDevDependencies && isset($lockData['packages-dev']) && \is_array(value: $lockData['packages-dev'])) { foreach ($lockData['packages-dev'] as $package) { - if (!isset($package['name']) || !\is_string($package['name'])) { + if (!isset($package['name']) || !\is_string(value: $package['name'])) { continue; } diff --git a/src/Source/Composer/Provider/CompositeComposerProvider.php b/src/Source/Composer/Provider/CompositeComposerProvider.php index 9261ce62..0d83ac90 100644 --- a/src/Source/Composer/Provider/CompositeComposerProvider.php +++ b/src/Source/Composer/Provider/CompositeComposerProvider.php @@ -21,7 +21,7 @@ public function __construct( ComposerProviderInterface ...$providers, ) { foreach ($providers as $provider) { - $this->addProvider($provider); + $this->addProvider(provider: $provider); } } @@ -45,7 +45,7 @@ public function getPackages(string $composerPath, bool $includeDevDependencies = $this->logger->info('Getting packages from composite provider', [ 'composerPath' => $composerPath, 'includeDevDependencies' => $includeDevDependencies, - 'providerCount' => \count($this->providers), + 'providerCount' => \count(value: $this->providers), ]); // If no providers, return empty collection @@ -72,12 +72,12 @@ public function getPackages(string $composerPath, bool $includeDevDependencies = // Merge packages into combined collection, new packages override existing ones foreach ($packages as $packageName => $package) { - if ($combinedPackages->has($packageName)) { + if ($combinedPackages->has(name: $packageName)) { $this->logger->debug('Package already exists in collection, overriding', [ 'package' => $packageName, ]); } - $combinedPackages->add($package); + $combinedPackages->add(package: $package); } $this->logger->info('Successfully fetched packages from provider', [ diff --git a/src/Source/Composer/Provider/LocalComposerProvider.php b/src/Source/Composer/Provider/LocalComposerProvider.php index 503050c7..79c66574 100644 --- a/src/Source/Composer/Provider/LocalComposerProvider.php +++ b/src/Source/Composer/Provider/LocalComposerProvider.php @@ -38,8 +38,8 @@ public function getPackages(string $composerPath, bool $includeDevDependencies = $composerData = $this->client->loadComposerData($composerPath); // Try to load composer.lock for more accurate version information - $lockData = $this->client->tryLoadComposerLock(\dirname($this->basePath . '/composer.json')); - $packageVersions = $this->extractPackageVersionsFromLock($lockData, $includeDevDependencies); + $lockData = $this->client->tryLoadComposerLock(\dirname(path: $this->basePath . '/composer.json')); + $packageVersions = $this->extractPackageVersionsFromLock(lockData: $lockData, includeDevDependencies: $includeDevDependencies); // Get vendor directory $vendorDir = $this->client->getVendorDir($composerData, $this->basePath); @@ -49,20 +49,20 @@ public function getPackages(string $composerPath, bool $includeDevDependencies = // Process regular dependencies $this->processPackages( - $packages, - $composerData['require'] ?? [], - $packageVersions, - $vendorDir, + packages: $packages, + dependencies: $composerData['require'] ?? [], + packageVersions: $packageVersions, + vendorDir: $vendorDir, ); // Process dev dependencies if requested - if ($includeDevDependencies && isset($composerData['require-dev']) && \is_array($composerData['require-dev'])) { + if ($includeDevDependencies && isset($composerData['require-dev']) && \is_array(value: $composerData['require-dev'])) { $this->processPackages( - $packages, - $composerData['require-dev'], - $packageVersions, - $vendorDir, - true, + packages: $packages, + dependencies: $composerData['require-dev'], + packageVersions: $packageVersions, + vendorDir: $vendorDir, + isDev: true, ); } @@ -91,18 +91,18 @@ private function processPackages( ): void { foreach ($dependencies as $packageName => $constraintVersion) { // Skip php and ext-* dependencies - if ($packageName === 'php' || \str_starts_with($packageName, 'ext-')) { + if ($packageName === 'php' || \str_starts_with(haystack: $packageName, needle: 'ext-')) { continue; } // Skip if already included in regular dependencies (for dev deps) - if ($isDev && $packages->has($packageName)) { + if ($isDev && $packages->has(name: $packageName)) { continue; } $packagePath = $this->basePath . '/' . $vendorDir . '/' . $packageName; - if (!\is_dir($packagePath)) { + if (!\is_dir(filename: $packagePath)) { $this->logger->warning('Package directory not found', [ 'package' => $packageName, 'path' => $packagePath, @@ -125,7 +125,7 @@ private function processPackages( } $packages->add( - new ComposerPackageInfo( + package: new ComposerPackageInfo( name: $packageName, path: $packagePath, version: $version, @@ -142,7 +142,7 @@ private function processPackages( // Add the package with minimal info $packages->add( - new ComposerPackageInfo( + package: new ComposerPackageInfo( name: $packageName, path: $packagePath, version: $version, diff --git a/src/Source/Docs/DocsSource.php b/src/Source/Docs/DocsSource.php index 612e17f4..eb086658 100644 --- a/src/Source/Docs/DocsSource.php +++ b/src/Source/Docs/DocsSource.php @@ -31,12 +31,12 @@ public function __construct( #[\Override] public function jsonSerialize(): array { - return \array_filter([ + return \array_filter(array: [ 'type' => 'docs', ...parent::jsonSerialize(), 'library' => $this->library, 'topic' => $this->topic, 'tokens' => $this->tokens, - ], static fn($value) => $value !== null && $value !== '' && $value !== []); + ], callback: static fn($value) => $value !== null && $value !== '' && $value !== []); } } diff --git a/src/Source/Docs/DocsSourceBootloader.php b/src/Source/Docs/DocsSourceBootloader.php index c22bf24d..bd022c98 100644 --- a/src/Source/Docs/DocsSourceBootloader.php +++ b/src/Source/Docs/DocsSourceBootloader.php @@ -39,7 +39,7 @@ public function init( SourceRegistryInterface $sourceRegistry, DocsSourceFactory $factory, ): void { - $registry->register(DocsSourceFetcher::class); + $registry->register(fetcher: DocsSourceFetcher::class); $sourceRegistry->register($factory); } } diff --git a/src/Source/Docs/DocsSourceFactory.php b/src/Source/Docs/DocsSourceFactory.php index f6d1bd7a..9ca923c4 100644 --- a/src/Source/Docs/DocsSourceFactory.php +++ b/src/Source/Docs/DocsSourceFactory.php @@ -25,16 +25,16 @@ public function create(array $config): DocsSource 'config' => $config, ]); - if (!isset($config['library']) || !\is_string($config['library'])) { - throw new \RuntimeException('Docs source must have a "library" string property'); + if (!isset($config['library']) || !\is_string(value: $config['library'])) { + throw new \RuntimeException(message: 'Docs source must have a "library" string property'); } - if (!isset($config['topic']) || !\is_string($config['topic'])) { - throw new \RuntimeException('Docs source must have a "topic" string property'); + if (!isset($config['topic']) || !\is_string(value: $config['topic'])) { + throw new \RuntimeException(message: 'Docs source must have a "topic" string property'); } $tokens = 2000; - if (isset($config['tokens']) && (\is_int($config['tokens']) || \is_string($config['tokens']))) { + if (isset($config['tokens']) && (\is_int(value: $config['tokens']) || \is_string(value: $config['tokens']))) { $tokens = (int) $config['tokens']; } diff --git a/src/Source/Docs/DocsSourceFetcher.php b/src/Source/Docs/DocsSourceFetcher.php index 58f8543f..9ab6aab3 100644 --- a/src/Source/Docs/DocsSourceFetcher.php +++ b/src/Source/Docs/DocsSourceFetcher.php @@ -54,7 +54,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $this->logger->error($errorMessage, [ 'sourceType' => $source::class, ]); - throw new \InvalidArgumentException($errorMessage); + throw new \InvalidArgumentException(message: $errorMessage); } $this->logger->info('Fetching documentation from Context7', [ @@ -66,11 +66,11 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi // Create builder $builder = $this->builderFactory ->create() - ->addDescription($this->variableResolver->resolve($source->getDescription())); + ->addDescription(description: $this->variableResolver->resolve(strings: $source->getDescription())); try { - $library = $this->variableResolver->resolve($source->library); - $topic = $this->variableResolver->resolve($source->topic); + $library = $this->variableResolver->resolve(strings: $source->library); + $topic = $this->variableResolver->resolve(strings: $source->topic); $tokens = $source->tokens; // Build the URL for Context7 API @@ -78,7 +78,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi '%s/%s/llms.txt?topic=%s&tokens=%d', self::CONTEXT7_BASE_URL, $library, - \rawurlencode($topic), + \rawurlencode(string: $topic), $tokens, ); @@ -88,7 +88,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi ]); // Send the request - $requestHeaders = $this->variableResolver->resolve($this->defaultHeaders); + $requestHeaders = $this->variableResolver->resolve(strings: $this->defaultHeaders); $response = $this->httpClient->get($url, $requestHeaders); $statusCode = $response->getStatusCode(); @@ -99,9 +99,9 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi ]); $builder - ->addComment("Library: {$library}") - ->addComment("Topic: {$topic}") - ->addComment("Error: HTTP status code {$statusCode}") + ->addComment(comment: "Library: {$library}") + ->addComment(comment: "Topic: {$topic}") + ->addComment(comment: "Error: HTTP status code {$statusCode}") ->addSeparator(); return $builder->build(); } @@ -113,7 +113,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi // Get the response body $content = $response->getBody(); - $contentLength = \strlen($content); + $contentLength = \strlen(string: $content); $this->logger->debug('Received documentation content', [ 'library' => $library, @@ -123,16 +123,16 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi // Add metadata to the builder $builder - ->addComment("Library: {$library}") - ->addComment("Topic: {$topic}") - ->addComment("Tokens: {$tokens}") + ->addComment(comment: "Library: {$library}") + ->addComment(comment: "Topic: {$topic}") + ->addComment(comment: "Tokens: {$tokens}") ->addSeparator(); // Apply modifiers to the content $processedContent = $modifiersApplier->apply($content, $url); // Add the processed content to the builder - $builder->addText($processedContent); + $builder->addText(text: $processedContent); } catch (\Throwable $e) { $this->logger->error('Error retrieving documentation from Context7', [ 'library' => $source->library ?? 'unknown', @@ -143,15 +143,15 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi ]); $builder - ->addComment("Library: {$source->library}") - ->addComment("Topic: {$source->topic}") - ->addComment("Error: {$e->getMessage()}") + ->addComment(comment: "Library: {$source->library}") + ->addComment(comment: "Topic: {$source->topic}") + ->addComment(comment: "Error: {$e->getMessage()}") ->addSeparator(); } $content = $builder->build(); $this->logger->info('Documentation content fetched successfully', [ - 'contentLength' => \strlen($content), + 'contentLength' => \strlen(string: $content), ]); // Return built content diff --git a/src/Source/Fetcher/SourceFetcherBootloader.php b/src/Source/Fetcher/SourceFetcherBootloader.php index 8a478818..34c1eef9 100644 --- a/src/Source/Fetcher/SourceFetcherBootloader.php +++ b/src/Source/Fetcher/SourceFetcherBootloader.php @@ -37,8 +37,8 @@ public function defineSingletons(): array $fetchers = $bootloader->getFetchers(); return new SourceFetcherProvider( fetchers: \array_map( - static fn(string $fetcher) => $container->get($fetcher), - $fetchers, + callback: static fn(string $fetcher) => $container->get(id: $fetcher), + array: $fetchers, ), ); }, diff --git a/src/Source/Fetcher/SourceFetcherProvider.php b/src/Source/Fetcher/SourceFetcherProvider.php index 8a1d6332..a88eb01e 100644 --- a/src/Source/Fetcher/SourceFetcherProvider.php +++ b/src/Source/Fetcher/SourceFetcherProvider.php @@ -32,7 +32,7 @@ public function findFetcher(SourceInterface $source): SourceFetcherInterface } throw new \RuntimeException( - \sprintf( + message: \sprintf( 'No fetcher found for source of type %s', $source::class, ), @@ -41,6 +41,6 @@ public function findFetcher(SourceInterface $source): SourceFetcherInterface public function parse(SourceInterface $source, ModifiersApplierInterface $modifiersApplier): string { - return $this->findFetcher($source)->fetch($source, $modifiersApplier); + return $this->findFetcher(source: $source)->fetch($source, $modifiersApplier); } } diff --git a/src/Source/File/FileSource.php b/src/Source/File/FileSource.php index 0ca081df..2a0fca73 100644 --- a/src/Source/File/FileSource.php +++ b/src/Source/File/FileSource.php @@ -89,7 +89,7 @@ public function in(): array|null // Extract directories from sourcePaths foreach ((array) $this->sourcePaths as $path) { - if (\is_dir($path)) { + if (\is_dir(filename: $path)) { $directories[] = $path; } } @@ -103,7 +103,7 @@ public function files(): array|null // Extract files from sourcePaths foreach ((array) $this->sourcePaths as $path) { - if (\is_file($path)) { + if (\is_file(filename: $path)) { $files[] = $path; } } @@ -163,6 +163,6 @@ public function jsonSerialize(): array $result['maxFiles'] = $this->maxFiles; } - return \array_filter($result); + return \array_filter(array: $result); } } diff --git a/src/Source/File/FileSourceBootloader.php b/src/Source/File/FileSourceBootloader.php index f474b0d8..3ecb2c73 100644 --- a/src/Source/File/FileSourceBootloader.php +++ b/src/Source/File/FileSourceBootloader.php @@ -35,7 +35,7 @@ public function init( SourceRegistryInterface $sourceRegistry, FileSourceFactory $factory, ): void { - $registry->register(FileSourceFetcher::class); + $registry->register(fetcher: FileSourceFetcher::class); $sourceRegistry->register($factory); } } diff --git a/src/Source/File/FileSourceFactory.php b/src/Source/File/FileSourceFactory.php index f779281e..46452db6 100644 --- a/src/Source/File/FileSourceFactory.php +++ b/src/Source/File/FileSourceFactory.php @@ -28,35 +28,35 @@ public function create(array $config): SourceInterface ]); if (isset($config['modifiers'])) { - $config['modifiers'] = $this->parseModifiers($config['modifiers']); + $config['modifiers'] = $this->parseModifiers(modifiersConfig: $config['modifiers']); } if (!isset($config['sourcePaths'])) { - throw new \RuntimeException('File source must have a "sourcePaths" property'); + throw new \RuntimeException(message: 'File source must have a "sourcePaths" property'); } $sourcePaths = $config['sourcePaths']; - if (!\is_string($sourcePaths) && !\is_array($sourcePaths)) { - throw new \RuntimeException('"sourcePaths" must be a string or array in source'); + if (!\is_string(value: $sourcePaths) && !\is_array(value: $sourcePaths)) { + throw new \RuntimeException(message: '"sourcePaths" must be a string or array in source'); } - $sourcePaths = \is_string($sourcePaths) ? [$sourcePaths] : $sourcePaths; + $sourcePaths = \is_string(value: $sourcePaths) ? [$sourcePaths] : $sourcePaths; $sourcePaths = \array_map( - fn(string $sourcePath): string => (string) $this->dirs->getRootPath()->join($sourcePath), - $sourcePaths, + callback: fn(string $sourcePath): string => (string) $this->dirs->getRootPath()->join($sourcePath), + array: $sourcePaths, ); // Validate filePattern if present if (isset($config['filePattern'])) { - if (!\is_string($config['filePattern']) && !\is_array($config['filePattern'])) { - throw new \RuntimeException('filePattern must be a string or an array of strings'); + if (!\is_string(value: $config['filePattern']) && !\is_array(value: $config['filePattern'])) { + throw new \RuntimeException(message: 'filePattern must be a string or an array of strings'); } // If it's an array, make sure all elements are strings - if (\is_array($config['filePattern'])) { + if (\is_array(value: $config['filePattern'])) { foreach ($config['filePattern'] as $pattern) { - if (!\is_string($pattern)) { - throw new \RuntimeException('All elements in filePattern must be strings'); + if (!\is_string(value: $pattern)) { + throw new \RuntimeException(message: 'All elements in filePattern must be strings'); } } } @@ -64,12 +64,12 @@ public function create(array $config): SourceInterface // Validate maxFiles if present if (isset($config['maxFiles']) && $config['maxFiles'] !== null) { - if (!\is_int($config['maxFiles'])) { - throw new \RuntimeException('maxFiles must be an integer or null'); + if (!\is_int(value: $config['maxFiles'])) { + throw new \RuntimeException(message: 'maxFiles must be an integer or null'); } if ($config['maxFiles'] < 0) { - throw new \RuntimeException('maxFiles cannot be negative'); + throw new \RuntimeException(message: 'maxFiles cannot be negative'); } } @@ -91,7 +91,7 @@ public function create(array $config): SourceInterface size: $config['size'] ?? [], date: $config['date'] ?? [], ignoreUnreadableDirs: $config['ignoreUnreadableDirs'] ?? false, - treeView: TreeViewConfig::fromArray($config), + treeView: TreeViewConfig::fromArray(data: $config), maxFiles: $config['maxFiles'] ?? 0, modifiers: $config['modifiers'] ?? [], tags: $config['tags'] ?? [], diff --git a/src/Source/File/FileSourceFetcher.php b/src/Source/File/FileSourceFetcher.php index 179c5059..2015ea61 100644 --- a/src/Source/File/FileSourceFetcher.php +++ b/src/Source/File/FileSourceFetcher.php @@ -44,7 +44,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $this->logger?->error($errorMessage, [ 'sourceType' => $source::class, ]); - throw new \InvalidArgumentException($errorMessage); + throw new \InvalidArgumentException(message: $errorMessage); } $this->logger?->info('Fetching file source content', [ @@ -56,7 +56,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $this->logger?->debug('Creating content builder'); $builder = $this->builderFactory ->create() - ->addTitle($source->getDescription()); + ->addTitle(title: $source->getDescription()); // Execute find operation and get the result $this->logger?->debug('Finding files', [ @@ -69,12 +69,12 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $fileCount = $finderResult->count(); $this->logger?->debug('Files found', ['fileCount' => $fileCount]); } catch (\Throwable $e) { - if (\str_contains($e->getMessage(), 'must call one of in() or append() methods')) { + if (\str_contains(haystack: $e->getMessage(), needle: 'must call one of in() or append() methods')) { $errorMessage = \sprintf( 'Some directories or files contain invalid paths: %s', \implode( - ', ', - [ + separator: ', ', + array: [ ...(array) $source->in(), ...(array) $source->files(), ], @@ -83,7 +83,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $this->logger?->error($errorMessage, [ 'error' => $e->getMessage(), ]); - throw new \RuntimeException($errorMessage); + throw new \RuntimeException(message: $errorMessage); } $errorMessage = \sprintf('Error while finding files: %s', $e->getMessage()); @@ -92,13 +92,13 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi 'file' => $e->getFile(), 'line' => $e->getLine(), ]); - throw new \RuntimeException($errorMessage); + throw new \RuntimeException(message: $errorMessage); } // Generate tree view if requested if ($source->treeView->enabled) { $this->logger?->debug('Adding tree view to output'); - $builder->addTreeView($finderResult->treeView); + $builder->addTreeView(treeView: $finderResult->treeView); } // Process each file @@ -115,7 +115,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi ); } - $relativePath = \trim(\str_replace($this->basePath, '', $file->getPath())); + $relativePath = \trim(string: \str_replace(search: $this->basePath, replace: '', subject: $file->getPath())); $fileName = $file->getFilename(); $filePath = empty($relativePath) ? $fileName : "$relativePath/$fileName"; @@ -126,13 +126,13 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi 'size' => $file->getSize(), ]); - $language = $this->detectLanguage($filePath); - $content = $modifiersApplier->apply($this->getContent($file, $source), $fileName); + $language = $this->detectLanguage(filePath: $filePath); + $content = $modifiersApplier->apply($this->getContent(file: $file, source: $source), $fileName); $this->logger?->debug('Adding file to content', [ 'file' => $filePath, 'language' => $language, - 'contentLength' => \strlen($content), + 'contentLength' => \strlen(string: $content), ]); $builder->addCodeBlock( @@ -145,7 +145,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $content = $builder->build(); $this->logger?->info('File source content fetched successfully', [ 'fileCount' => $fileCount, - 'contentLength' => \strlen($content), + 'contentLength' => \strlen(string: $content), ]); // Return built content @@ -161,7 +161,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi */ protected function getContent(SplFileInfo $file, SourceInterface $source): string { - \assert($source instanceof FileSource); + \assert(assertion: $source instanceof FileSource); $filePath = $file->getRelativePathname(); $this->logger?->debug('Reading file content', ['file' => $filePath]); @@ -170,7 +170,7 @@ protected function getContent(SplFileInfo $file, SourceInterface $source): strin private function detectLanguage(string $filePath): ?string { - $extension = \pathinfo($filePath, PATHINFO_EXTENSION); + $extension = \pathinfo(path: $filePath, flags: PATHINFO_EXTENSION); $this->logger?->debug('Detecting language for file', [ 'file' => $filePath, diff --git a/src/Source/File/SymfonyFinder.php b/src/Source/File/SymfonyFinder.php index c58df7e9..6389cc0f 100644 --- a/src/Source/File/SymfonyFinder.php +++ b/src/Source/File/SymfonyFinder.php @@ -40,53 +40,53 @@ public function find(FilterableSourceInterface $source, string $basePath = '', a $files = $source->files(); if (!empty($directories)) { - $finder->in($directories); + $finder->in(dirs: $directories); } if (!empty($files)) { - $finder->append($files); + $finder->append(iterator: $files); } // Configure name pattern for file matching $namePattern = $source->name(); if ($namePattern !== null) { - $finder->name($namePattern); + $finder->name(patterns: $namePattern); } // Configure path pattern $pathPattern = $source->path(); if ($pathPattern !== null) { - $finder->path($pathPattern); + $finder->path(patterns: $pathPattern); } // Configure notPath pattern $notPathPattern = $source->notPath(); if ($notPathPattern !== null) { - $finder->notPath($notPathPattern); + $finder->notPath(patterns: $notPathPattern); } // Configure contains pattern $containsPattern = $source->contains(); if ($containsPattern !== null) { - $finder->contains($containsPattern); + $finder->contains(patterns: $containsPattern); } // Configure notContains pattern $notContainsPattern = $source->notContains(); if ($notContainsPattern !== null) { - $finder->notContains($notContainsPattern); + $finder->notContains(patterns: $notContainsPattern); } // Configure size constraints $sizeConstraints = $source->size(); if ($sizeConstraints !== null) { - $finder->size($sizeConstraints); + $finder->size(sizes: $sizeConstraints); } // Configure date constraints $dateConstraints = $source->date(); if ($dateConstraints !== null) { - $finder->date($dateConstraints); + $finder->date(dates: $dateConstraints); } // Configure ignoreUnreadableDirs @@ -96,7 +96,7 @@ public function find(FilterableSourceInterface $source, string $basePath = '', a // Apply depth constraint if maxDepth is set if (isset($options['maxDepth']) && $options['maxDepth'] > 0) { - $finder->depth('<= ' . $options['maxDepth']); + $finder->depth(levels: '<= ' . $options['maxDepth']); } $finder->sortByName(); @@ -106,7 +106,7 @@ public function find(FilterableSourceInterface $source, string $basePath = '', a $hasLimit = $maxFiles !== null && $maxFiles > 0; // Generate tree view (always on all files for consistency) - $treeView = $this->generateTreeView($finder, $basePath, $options); + $treeView = $this->generateTreeView(finder: $finder, basePath: $basePath, options: $options); // Get files with limit if needed if ($hasLimit) { @@ -132,7 +132,7 @@ public function find(FilterableSourceInterface $source, string $basePath = '', a $files = []; foreach ($finder as $file) { // Skip files that would be excluded by path patterns - if ($this->shouldExcludeFile($this->getPath($file, $basePath))) { + if ($this->shouldExcludeFile(filePath: $this->getPath(file: $file, basePath: $basePath))) { continue; } @@ -160,7 +160,7 @@ private function generateTreeView(Finder $finder, string $basePath, array $optio foreach ($finder as $file) { // Skip excluded files in tree view - if ($this->shouldExcludeFile($this->getPath($file, $basePath))) { + if ($this->shouldExcludeFile(filePath: $this->getPath(file: $file, basePath: $basePath))) { continue; } @@ -171,7 +171,7 @@ private function generateTreeView(Finder $finder, string $basePath, array $optio return "No files found.\n"; } - return $this->fileTreeBuilder->buildTree($filePaths, $basePath, $options); + return $this->fileTreeBuilder->buildTree(files: $filePaths, basePath: $basePath, options: $options); } /** @@ -188,6 +188,6 @@ private function getPath(SplFileInfo|\SplFileInfo $file, string $basePath) return $file->getRelativePathname(); } - return \ltrim(\str_replace($basePath, '', $file->getRealPath()), '/'); + return \ltrim(string: \str_replace(search: $basePath, replace: '', subject: $file->getRealPath()), characters: '/'); } } diff --git a/src/Source/GitDiff/Fetcher/CommitRangeParser.php b/src/Source/GitDiff/Fetcher/CommitRangeParser.php index d22bd5f2..428b5026 100644 --- a/src/Source/GitDiff/Fetcher/CommitRangeParser.php +++ b/src/Source/GitDiff/Fetcher/CommitRangeParser.php @@ -64,11 +64,11 @@ */ public function resolve(string|array $commitRange): string|array { - if (\is_array($commitRange)) { - return \array_map(fn(string $range): string => $this->resolveExpression($range), $commitRange); + if (\is_array(value: $commitRange)) { + return \array_map(callback: fn(string $range): string => $this->resolveExpression(expression: $range), array: $commitRange); } - return $this->resolveExpression($commitRange); + return $this->resolveExpression(expression: $commitRange); } /** @@ -90,50 +90,50 @@ public function resolveExpression(string $expression): string // Handle specific commit patterns // 1. Check for a specific commit hash (must be at least 7 chars) - if (\preg_match('/^[0-9a-f]{7,40}$/', $expression)) { + if (\preg_match(pattern: '/^[0-9a-f]{7,40}$/', subject: $expression)) { return $expression . '~1..' . $expression; } // 2. Check for specific commit with file pattern: abc1234:path/to/file.php - if (\preg_match('/^([0-9a-f]{7,40}):(.+)$/', $expression, $matches)) { + if (\preg_match(pattern: '/^([0-9a-f]{7,40}):(.+)$/', subject: $expression, matches: $matches)) { return $matches[1] . ' -- ' . $matches[2]; } // 3. Check for tag or branch comparison: tag:v1.0.0 or branch:feature/name - if (\preg_match('/^(tag|branch):(.+)$/', $expression, $matches)) { + if (\preg_match(pattern: '/^(tag|branch):(.+)$/', subject: $expression, matches: $matches)) { $ref = $matches[2]; return $ref . '~1..' . $ref; } // 4. Check for branch comparison: main..feature - if (\preg_match('/^([^\.]+)\.\.([^\.]+)$/', $expression)) { + if (\preg_match(pattern: '/^([^\.]+)\.\.([^\.]+)$/', subject: $expression)) { // This is already a valid git range - return as is return $expression; } // 5. Check for 'since:' pattern to specify a starting point - if (\preg_match('/^since:(.+)$/', $expression, $matches)) { + if (\preg_match(pattern: '/^since:(.+)$/', subject: $expression, matches: $matches)) { return $matches[1] . '..HEAD'; } // 6. Handle stash pattern: stash@{n} or stash@{/message} - if (\preg_match('/^stash@\{.+\}$/', $expression)) { + if (\preg_match(pattern: '/^stash@\{.+\}$/', subject: $expression)) { // This is already a valid stash reference - return as is return $expression; } // 7. Handle numeric stash pattern: stash:0, stash:1, etc. - if (\preg_match('/^stash:(\d+)$/', $expression, $matches)) { + if (\preg_match(pattern: '/^stash:(\d+)$/', subject: $expression, matches: $matches)) { return 'stash@{' . $matches[1] . '}'; } // 8. Handle stash message pattern: stash:/message - if (\preg_match('/^stash:\/(.+)$/', $expression, $matches)) { + if (\preg_match(pattern: '/^stash:\/(.+)$/', subject: $expression, matches: $matches)) { return 'stash@{/' . $matches[1] . '}'; } // Handle ISO-8601 date format: @2023-01-15 or date:2023-01-15 - if (\preg_match('/^(?:@|date:)(\d{4}-\d{2}-\d{2})$/', $expression, $matches)) { + if (\preg_match(pattern: '/^(?:@|date:)(\d{4}-\d{2}-\d{2})$/', subject: $expression, matches: $matches)) { return '--since=' . $matches[1] . ' --until=' . $matches[1] . ' 23:59:59'; } diff --git a/src/Source/GitDiff/Fetcher/GitSourceFactory.php b/src/Source/GitDiff/Fetcher/GitSourceFactory.php index f5107173..c8070054 100644 --- a/src/Source/GitDiff/Fetcher/GitSourceFactory.php +++ b/src/Source/GitDiff/Fetcher/GitSourceFactory.php @@ -21,7 +21,7 @@ public function __construct( public function create(string $commitReference): GitSourceInterface { - return $this->createForSingleReference($commitReference); + return $this->createForSingleReference(commitReference: $commitReference); } /** diff --git a/src/Source/GitDiff/Fetcher/Source/AbstractGitSource.php b/src/Source/GitDiff/Fetcher/Source/AbstractGitSource.php index 2a6472f5..1ac55ee8 100644 --- a/src/Source/GitDiff/Fetcher/Source/AbstractGitSource.php +++ b/src/Source/GitDiff/Fetcher/Source/AbstractGitSource.php @@ -23,7 +23,7 @@ public function __construct( public function createFileInfos(string $repository, string $commitReference, string $tempDir): array { - $changedFiles = $this->getChangedFiles($repository, $commitReference); + $changedFiles = $this->getChangedFiles(repository: $repository, commitReference: $commitReference); if (empty($changedFiles)) { return []; @@ -36,14 +36,14 @@ public function createFileInfos(string $repository, string $commitReference, str foreach ($changedFiles as $file) { // Get the diff for this file - $diff = $this->getFileDiff($repository, $commitReference, $file); + $diff = $this->getFileDiff(repository: $repository, commitReference: $commitReference, file: $file); if (empty($diff)) { continue; } // Create the temporary file - $tempFile = FSPath::create($tempDir)->join($file); + $tempFile = FSPath::create(path: $tempDir)->join($file); $tempDirname = (string) $tempFile->parent(); $this->files->ensureDirectory($tempDirname, 0777); @@ -58,7 +58,7 @@ public function __construct( string $originalPath, private readonly string $diffContent, ) { - parent::__construct($tempFile, \dirname($originalPath), $originalPath); + parent::__construct($tempFile, \dirname(path: $originalPath), $originalPath); $this->originalPath = $originalPath; } @@ -94,9 +94,9 @@ protected function executeGitCommand(string $repository, string $command): array try { $result = $this->executeGitCommandString(repository: $repository, command: $command); // Normalize line endings to Unix format - $result = \str_replace("\r\n", "\n", $result); + $result = \str_replace(search: "\r\n", replace: "\n", subject: $result); - return \array_map(\trim(...), \array_filter(\explode("\n", $result))); + return \array_map(callback: \trim(...), array: \array_filter(array: \explode(separator: "\n", string: $result))); } catch (GitCommandException $e) { $this->logger?->warning('Git command failed, returning empty result', [ 'command' => $command, diff --git a/src/Source/GitDiff/Fetcher/Source/CommitGitSource.php b/src/Source/GitDiff/Fetcher/Source/CommitGitSource.php index 8d828f80..79205473 100644 --- a/src/Source/GitDiff/Fetcher/Source/CommitGitSource.php +++ b/src/Source/GitDiff/Fetcher/Source/CommitGitSource.php @@ -15,12 +15,12 @@ public function supports(string $commitReference): bool { // Basic commit range like commit1..commit2 - if (\preg_match('/^[^\.]+\.\.[^\.]+$/', $commitReference)) { + if (\preg_match(pattern: '/^[^\.]+\.\.[^\.]+$/', subject: $commitReference)) { return true; } // Single commit hash like abc1234 - if (\preg_match('/^[0-9a-f]{7,40}$/', $commitReference)) { + if (\preg_match(pattern: '/^[0-9a-f]{7,40}$/', subject: $commitReference)) { return true; } @@ -36,7 +36,7 @@ public function supports(string $commitReference): bool 'develop..HEAD', ]; - if (\in_array($commitReference, $commonFormats, true)) { + if (\in_array(needle: $commitReference, haystack: $commonFormats, strict: true)) { return true; } diff --git a/src/Source/GitDiff/Fetcher/Source/FileAtCommitGitSource.php b/src/Source/GitDiff/Fetcher/Source/FileAtCommitGitSource.php index 9ab038e3..db810bdf 100644 --- a/src/Source/GitDiff/Fetcher/Source/FileAtCommitGitSource.php +++ b/src/Source/GitDiff/Fetcher/Source/FileAtCommitGitSource.php @@ -15,12 +15,12 @@ public function supports(string $commitReference): bool { // Support format: commit -- path - return \str_contains($commitReference, ' -- '); + return \str_contains(haystack: $commitReference, needle: ' -- '); } public function getChangedFiles(string $repository, string $commitReference): array { - [$commit, $path] = \explode(' -- ', $commitReference, 2); + [$commit, $path] = \explode(separator: ' -- ', string: $commitReference, limit: 2); $output = $this->executeGitCommand( repository: $repository, @@ -28,19 +28,19 @@ public function getChangedFiles(string $repository, string $commitReference): ar ); // The first line is the commit hash, so skip it - if (!empty($output) && \preg_match('/^[0-9a-f]{40}$/', $output[0])) { - \array_shift($output); + if (!empty($output) && \preg_match(pattern: '/^[0-9a-f]{40}$/', subject: $output[0])) { + \array_shift(array: $output); } - return \array_filter($output); + return \array_filter(array: $output); } public function getFileDiff(string $repository, string $commitReference, string $file): string { - [$commit, $path] = \explode(' -- ', $commitReference, 2); + [$commit, $path] = \explode(separator: ' -- ', string: $commitReference, limit: 2); // Only process the file if it matches the path filter - if ($path !== $file && !\str_starts_with($file, $path)) { + if ($path !== $file && !\str_starts_with(haystack: $file, needle: $path)) { return ''; } @@ -52,7 +52,7 @@ public function getFileDiff(string $repository, string $commitReference, string public function formatReferenceForDisplay(string $commitReference): string { - [$commit, $path] = \explode(' -- ', $commitReference, 2); + [$commit, $path] = \explode(separator: ' -- ', string: $commitReference, limit: 2); return "Files at commit {$commit} with path: {$path}"; } diff --git a/src/Source/GitDiff/Fetcher/Source/StashGitSource.php b/src/Source/GitDiff/Fetcher/Source/StashGitSource.php index d5ad8e01..876780c8 100644 --- a/src/Source/GitDiff/Fetcher/Source/StashGitSource.php +++ b/src/Source/GitDiff/Fetcher/Source/StashGitSource.php @@ -15,17 +15,17 @@ public function supports(string $commitReference): bool { // Support regular stash references like stash@{0} - if (\preg_match('/^stash@\{\d+\}$/', $commitReference)) { + if (\preg_match(pattern: '/^stash@\{\d+\}$/', subject: $commitReference)) { return true; } // Support stash ranges like stash@{0}..stash@{2} - if (\preg_match('/^stash@\{\d+\}\.\.stash@\{\d+\}$/', $commitReference)) { + if (\preg_match(pattern: '/^stash@\{\d+\}\.\.stash@\{\d+\}$/', subject: $commitReference)) { return true; } // Support stash with message search like stash@{/message} - if (\preg_match('/^stash@\{\/(.*)\}$/', $commitReference)) { + if (\preg_match(pattern: '/^stash@\{\/(.*)\}$/', subject: $commitReference)) { return true; } @@ -35,7 +35,7 @@ public function supports(string $commitReference): bool public function getChangedFiles(string $repository, string $commitReference): array { // Handle single stash reference: stash@{0} - if (\preg_match('/^stash@\{\d+\}$/', $commitReference)) { + if (\preg_match(pattern: '/^stash@\{\d+\}$/', subject: $commitReference)) { return $this->executeGitCommand( repository: $repository, command: 'stash show --name-only ' . $commitReference, @@ -43,12 +43,12 @@ public function getChangedFiles(string $repository, string $commitReference): ar } // Handle stash range: stash@{0}..stash@{2} - if (\preg_match('/^stash@\{\d+\}\.\.stash@\{\d+\}$/', $commitReference)) { - [$startStash, $endStash] = \explode('..', $commitReference); + if (\preg_match(pattern: '/^stash@\{\d+\}\.\.stash@\{\d+\}$/', subject: $commitReference)) { + [$startStash, $endStash] = \explode(separator: '..', string: $commitReference); // Extract stash indices - \preg_match('/stash@\{(\d+)\}/', $startStash, $startMatches); - \preg_match('/stash@\{(\d+)\}/', $endStash, $endMatches); + \preg_match(pattern: '/stash@\{(\d+)\}/', subject: $startStash, matches: $startMatches); + \preg_match(pattern: '/stash@\{(\d+)\}/', subject: $endStash, matches: $endMatches); $startIndex = (int) $startMatches[1]; $endIndex = (int) $endMatches[1]; @@ -71,11 +71,11 @@ public function getChangedFiles(string $repository, string $commitReference): ar } } - return \array_unique($allFiles); + return \array_unique(array: $allFiles); } // Handle stash with message search: stash@{/message} - if (\preg_match('/^stash@\{\/(.*)\}$/', $commitReference, $matches)) { + if (\preg_match(pattern: '/^stash@\{\/(.*)\}$/', subject: $commitReference, matches: $matches)) { // Extract message search pattern $searchPattern = $matches[1] ?? ''; if (empty($searchPattern)) { @@ -95,7 +95,7 @@ public function getChangedFiles(string $repository, string $commitReference): ar // Find matching stash $matchingStashIndex = null; foreach ($listOutput as $index => $stashEntry) { - if (\stripos($stashEntry, $searchPattern) !== false) { + if (\stripos(haystack: $stashEntry, needle: $searchPattern) !== false) { $matchingStashIndex = $index; break; } @@ -117,10 +117,10 @@ public function getChangedFiles(string $repository, string $commitReference): ar public function getFileDiff(string $repository, string $commitReference, string $file): string { // Handle single stash reference: stash@{0} - if (\preg_match('/^stash@\{\d+\}$/', $commitReference)) { + if (\preg_match(pattern: '/^stash@\{\d+\}$/', subject: $commitReference)) { // FIX: Use the correct syntax for showing a file in a stash // The stash index needs to be extracted without the stash@{} syntax - \preg_match('/^stash@\{(\d+)\}$/', $commitReference, $matches); + \preg_match(pattern: '/^stash@\{(\d+)\}$/', subject: $commitReference, matches: $matches); $stashIndex = $matches[1] ?? 0; // Build the command with the stash index @@ -131,10 +131,10 @@ public function getFileDiff(string $repository, string $commitReference, string } // Handle stash range (just use the first stash in the range for showing diff) - if (\preg_match('/^stash@\{\d+\}\.\.stash@\{\d+\}$/', $commitReference)) { - [$startStash,] = \explode('..', $commitReference); + if (\preg_match(pattern: '/^stash@\{\d+\}\.\.stash@\{\d+\}$/', subject: $commitReference)) { + [$startStash,] = \explode(separator: '..', string: $commitReference); // Extract the stash index from startStash - \preg_match('/^stash@\{(\d+)\}$/', $startStash, $matches); + \preg_match(pattern: '/^stash@\{(\d+)\}$/', subject: $startStash, matches: $matches); $stashIndex = $matches[1] ?? 0; // Build the command @@ -145,7 +145,7 @@ public function getFileDiff(string $repository, string $commitReference, string } // Handle stash with message search: stash@{/message} - if (\preg_match('/^stash@\{\/(.*)\}$/', $commitReference, $matches)) { + if (\preg_match(pattern: '/^stash@\{\/(.*)\}$/', subject: $commitReference, matches: $matches)) { // Extract message search pattern $searchPattern = $matches[1] ?? ''; if (empty($searchPattern)) { @@ -165,7 +165,7 @@ public function getFileDiff(string $repository, string $commitReference, string // Find matching stash $matchingStashIndex = null; foreach ($listOutput as $index => $stashEntry) { - if (\stripos($stashEntry, $searchPattern) !== false) { + if (\stripos(haystack: $stashEntry, needle: $searchPattern) !== false) { $matchingStashIndex = $index; break; } diff --git a/src/Source/GitDiff/Fetcher/Source/TimeRangeGitSource.php b/src/Source/GitDiff/Fetcher/Source/TimeRangeGitSource.php index 48538026..4c7f6417 100644 --- a/src/Source/GitDiff/Fetcher/Source/TimeRangeGitSource.php +++ b/src/Source/GitDiff/Fetcher/Source/TimeRangeGitSource.php @@ -15,12 +15,12 @@ public function supports(string $commitReference): bool { // Match time-based ranges like HEAD@{1.week.ago}..HEAD - if (\preg_match('/HEAD@\{.*\}\.\.HEAD/', $commitReference)) { + if (\preg_match(pattern: '/HEAD@\{.*\}\.\.HEAD/', subject: $commitReference)) { return true; } // Match --since= format - if (\str_contains($commitReference, '--since=')) { + if (\str_contains(haystack: $commitReference, needle: '--since=')) { return true; } @@ -36,19 +36,19 @@ public function supports(string $commitReference): bool 'HEAD@{1.year.ago}..HEAD', ]; - return \in_array($commitReference, $timeBasedPresets, true); + return \in_array(needle: $commitReference, haystack: $timeBasedPresets, strict: true); } public function getChangedFiles(string $repository, string $commitReference): array { - if (\str_contains($commitReference, '--since=')) { + if (\str_contains(haystack: $commitReference, needle: '--since=')) { $output = $this->executeGitCommand( repository: $repository, command: 'log ' . $commitReference . ' --name-only --pretty=format:""', ); // Remove empty lines and duplicates - return \array_unique(\array_filter($output)); + return \array_unique(array: \array_filter(array: $output)); } return $this->executeGitCommand( @@ -59,7 +59,7 @@ public function getChangedFiles(string $repository, string $commitReference): ar public function getFileDiff(string $repository, string $commitReference, string $file): string { - if (\str_contains($commitReference, '--since=')) { + if (\str_contains(haystack: $commitReference, needle: '--since=')) { return $this->executeGitCommandString( repository: $repository, command: \sprintf('log %s -p -- %s', $commitReference, $file), @@ -90,8 +90,8 @@ public function formatReferenceForDisplay(string $commitReference): string return "Changes from " . $humanReadable[$commitReference]; } - if (\str_contains($commitReference, '--since=')) { - $since = \str_replace('--since=', '', $commitReference); + if (\str_contains(haystack: $commitReference, needle: '--since=')) { + $since = \str_replace(search: '--since=', replace: '', subject: $commitReference); return "Changes since {$since}"; } diff --git a/src/Source/GitDiff/GitDiffFinder.php b/src/Source/GitDiff/GitDiffFinder.php index 980b3d9b..000b2e20 100644 --- a/src/Source/GitDiff/GitDiffFinder.php +++ b/src/Source/GitDiff/GitDiffFinder.php @@ -42,11 +42,11 @@ public function __construct( public function find(FilterableSourceInterface $source, string $basePath = '', array $options = []): FinderResult { if (!$source instanceof GitDiffSource) { - throw new \InvalidArgumentException('Source must be an instance of CommitDiffSource'); + throw new \InvalidArgumentException(message: 'Source must be an instance of CommitDiffSource'); } // Get the commit range from the source - $commitRange = $this->rangeParser->resolve($source->commit); + $commitRange = $this->rangeParser->resolve(commitRange: $source->commit); $this->logger?->debug('Resolved commit range', [ 'original' => $source->commit, @@ -54,7 +54,7 @@ public function find(FilterableSourceInterface $source, string $basePath = '', a ]); // Get the appropriate Git source for this commit range - $gitSource = $this->sourceFactory->create($commitRange); + $gitSource = $this->sourceFactory->create(commitReference: $commitRange); $this->logger?->debug('Selected Git source', [ 'source' => $gitSource::class, @@ -73,33 +73,33 @@ public function find(FilterableSourceInterface $source, string $basePath = '', a $this->logger?->info('No changes found for the commit range', [ 'commitRange' => $commitRange, ]); - return new FinderResult([], 'No changes found'); + return new FinderResult(files: [], treeView: 'No changes found'); } $this->logger?->debug('Found files', [ - 'count' => \count($fileInfos), + 'count' => \count(value: $fileInfos), ]); // Apply filters if needed - $fileInfos = $this->applyFilters($fileInfos, $source, $tempDir); + $fileInfos = $this->applyFilters(fileInfos: $fileInfos, source: $source, tempDir: $tempDir); $this->logger?->debug('After applying filters', [ - 'count' => \count($fileInfos), + 'count' => \count(value: $fileInfos), ]); // Get file paths for tree view $filePaths = \array_map( - static fn(SplFileInfo $fileInfo) - => \method_exists($fileInfo, 'getOriginalPath') + callback: static fn(SplFileInfo $fileInfo) + => \method_exists(object_or_class: $fileInfo, method: 'getOriginalPath') ? $fileInfo->getOriginalPath() : $fileInfo->getRelativePathname(), - $fileInfos, + array: $fileInfos, ); // Generate tree view - $treeView = $this->generateTreeView($filePaths, $gitSource, $commitRange, $options); + $treeView = $this->generateTreeView(files: $filePaths, gitSource: $gitSource, commitRange: $commitRange, options: $options); - return new FinderResult(\array_values($fileInfos), $treeView); + return new FinderResult(files: \array_values(array: $fileInfos), treeView: $treeView); } catch (\Throwable $e) { $this->logger?->error('Error finding git diffs', [ 'error' => $e->getMessage(), @@ -124,7 +124,7 @@ private function applyFilters(array $fileInfos, FilterableSourceInterface $sourc } $this->logger?->debug('Applying filters to file infos', [ - 'fileCount' => \count($fileInfos), + 'fileCount' => \count(value: $fileInfos), 'name' => $source->name(), 'path' => $source->path(), 'notPath' => $source->notPath(), @@ -133,50 +133,50 @@ private function applyFilters(array $fileInfos, FilterableSourceInterface $sourc ]); $finder = new Finder(); - $finder->in($tempDir); + $finder->in(dirs: $tempDir); // Apply name filter if ($source->name() !== null) { - $finder->name($source->name()); + $finder->name(patterns: $source->name()); } // Apply path filter if ($source->path() !== null) { - $finder->path($source->path()); + $finder->path(patterns: $source->path()); } // Apply notPath filter if ($source->notPath() !== null) { - $finder->notPath($source->notPath()); + $finder->notPath(patterns: $source->notPath()); } // Apply contains filter if ($source->contains() !== null) { - $finder->contains($source->contains()); + $finder->contains(patterns: $source->contains()); } // Apply notContains filter if ($source->notContains() !== null) { - $finder->notContains($source->notContains()); + $finder->notContains(patterns: $source->notContains()); } // Get the filtered files $filteredPaths = []; foreach ($finder as $file) { - $relativePath = FSPath::create($file->getPathname())->trim($tempDir)->toString(); + $relativePath = FSPath::create(path: $file->getPathname())->trim(path: $tempDir)->toString(); $filteredPaths[$relativePath] = true; } // Filter the file infos - $filtered = \array_filter($fileInfos, static function (SplFileInfo $fileInfo) use ($filteredPaths, $tempDir) { - $relativePath = FSPath::create($fileInfo->getPathname())->trim($tempDir)->toString(); + $filtered = \array_filter(array: $fileInfos, callback: static function (SplFileInfo $fileInfo) use ($filteredPaths, $tempDir) { + $relativePath = FSPath::create(path: $fileInfo->getPathname())->trim(path: $tempDir)->toString(); return isset($filteredPaths[$relativePath]); }); $this->logger?->debug('Filter results', [ - 'originalCount' => \count($fileInfos), - 'filteredCount' => \count($filtered), + 'originalCount' => \count(value: $fileInfos), + 'filteredCount' => \count(value: $filtered), ]); return $filtered; @@ -204,7 +204,7 @@ private function generateTreeView( $treeHeader = $gitSource->formatReferenceForDisplay($commitRange) . "\n"; // Build the tree - $tree = $this->fileTreeBuilder->buildTree($files, '', $options); + $tree = $this->fileTreeBuilder->buildTree(files: $files, basePath: '', options: $options); return $treeHeader . $tree; } diff --git a/src/Source/GitDiff/GitDiffSource.php b/src/Source/GitDiff/GitDiffSource.php index 9906b39f..1caa0215 100644 --- a/src/Source/GitDiff/GitDiffSource.php +++ b/src/Source/GitDiff/GitDiffSource.php @@ -106,7 +106,7 @@ public function maxFiles(): int #[\Override] public function jsonSerialize(): array { - return \array_filter([ + return \array_filter(array: [ 'type' => 'git_diff', ...parent::jsonSerialize(), 'repository' => $this->repository, @@ -117,6 +117,6 @@ public function jsonSerialize(): array 'contains' => $this->contains, 'notContains' => $this->notContains, 'render' => $this->renderConfig, - ], static fn($value) => $value !== null && $value !== '' && $value !== []); + ], callback: static fn($value) => $value !== null && $value !== '' && $value !== []); } } diff --git a/src/Source/GitDiff/GitDiffSourceBootloader.php b/src/Source/GitDiff/GitDiffSourceBootloader.php index 05106136..51d034f1 100644 --- a/src/Source/GitDiff/GitDiffSourceBootloader.php +++ b/src/Source/GitDiff/GitDiffSourceBootloader.php @@ -59,7 +59,7 @@ public function init( SourceRegistryInterface $sourceRegistry, GitDiffSourceFactory $factory, ): void { - $registry->register(GitDiffSourceFetcher::class); + $registry->register(fetcher: GitDiffSourceFetcher::class); $sourceRegistry->register($factory); } } diff --git a/src/Source/GitDiff/GitDiffSourceFactory.php b/src/Source/GitDiff/GitDiffSourceFactory.php index 18025a5b..066369ec 100644 --- a/src/Source/GitDiff/GitDiffSourceFactory.php +++ b/src/Source/GitDiff/GitDiffSourceFactory.php @@ -28,25 +28,25 @@ public function create(array $config): SourceInterface ]); $repository = $config['repository'] ?? '.'; - if (!\is_string($repository)) { - throw new \RuntimeException('"repository" must be a string in source'); + if (!\is_string(value: $repository)) { + throw new \RuntimeException(message: '"repository" must be a string in source'); } // Prepend root path if repository is relative - $repository = \str_starts_with($repository, '/') + $repository = \str_starts_with(haystack: $repository, needle: '/') ? $repository : (string) $this->dirs->getRootPath()->join($repository); // Validate filePattern if present if (isset($config['filePattern'])) { - if (!\is_string($config['filePattern']) && !\is_array($config['filePattern'])) { - throw new \RuntimeException('filePattern must be a string or an array of strings'); + if (!\is_string(value: $config['filePattern']) && !\is_array(value: $config['filePattern'])) { + throw new \RuntimeException(message: 'filePattern must be a string or an array of strings'); } // If it's an array, make sure all elements are strings - if (\is_array($config['filePattern'])) { + if (\is_array(value: $config['filePattern'])) { foreach ($config['filePattern'] as $pattern) { - if (!\is_string($pattern)) { - throw new \RuntimeException('All elements in filePattern must be strings'); + if (!\is_string(value: $pattern)) { + throw new \RuntimeException(message: 'All elements in filePattern must be strings'); } } } @@ -54,8 +54,8 @@ public function create(array $config): SourceInterface // Ensure commit is a string $commit = $config['commit'] ?? 'staged'; - if (isset($config['commit']) && !\is_string($commit)) { - throw new \RuntimeException('commit must be a string'); + if (isset($config['commit']) && !\is_string(value: $commit)) { + throw new \RuntimeException(message: 'commit must be a string'); } // Process render configuration - support both legacy and new options @@ -63,10 +63,10 @@ public function create(array $config): SourceInterface // Check if we have a render property with sub-properties if (isset($config['render'])) { - if (\is_array($config['render'])) { - $renderConfig = RenderConfig::fromArray($config['render']); - } elseif (\is_string($config['render'])) { - $renderConfig = RenderConfig::fromString($config['render']); + if (\is_array(value: $config['render'])) { + $renderConfig = RenderConfig::fromArray(data: $config['render']); + } elseif (\is_string(value: $config['render'])) { + $renderConfig = RenderConfig::fromString(render: $config['render']); } } diff --git a/src/Source/GitDiff/GitDiffSourceFetcher.php b/src/Source/GitDiff/GitDiffSourceFetcher.php index 31234386..42545b33 100644 --- a/src/Source/GitDiff/GitDiffSourceFetcher.php +++ b/src/Source/GitDiff/GitDiffSourceFetcher.php @@ -47,7 +47,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $this->logger?->error($errorMessage, [ 'sourceType' => $source::class, ]); - throw new \InvalidArgumentException($errorMessage); + throw new \InvalidArgumentException(message: $errorMessage); } $this->logger?->info('Fetching git diff source content', [ @@ -64,23 +64,23 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi ]); try { - $finderResult = $this->finder->find($source); + $finderResult = $this->finder->find(source: $source); // Extract diffs from the finder result $this->logger?->debug('Extracting diffs from finder result'); - $diffs = $this->extractDiffsFromFinderResult($finderResult); - $this->logger?->debug('Diffs extracted', ['diffCount' => \count($diffs)]); + $diffs = $this->extractDiffsFromFinderResult(finderResult: $finderResult); + $this->logger?->debug('Diffs extracted', ['diffCount' => \count(value: $diffs)]); // Format the output using the specified render strategy $this->logger?->debug('Using render strategy to format output', [ 'strategy' => $source->renderConfig->strategy, ]); - $content = $this->renderOutput($diffs, $finderResult->treeView, $source); + $content = $this->renderOutput(diffs: $diffs, treeView: $finderResult->treeView, source: $source); $this->logger?->info('Git diff source content fetched successfully', [ - 'diffCount' => \count($diffs), - 'contentLength' => \strlen($content), + 'diffCount' => \count(value: $diffs), + 'contentLength' => \strlen(string: $content), 'renderStrategy' => $source->renderConfig->strategy, ]); @@ -115,7 +115,7 @@ private function extractDiffsFromFinderResult(FinderResult $finderResult): array } // Get the original path and diff content - $originalPath = \method_exists($file, 'getOriginalPath') + $originalPath = \method_exists(object_or_class: $file, method: 'getOriginalPath') ? $file->getOriginalPath() : $file->getRelativePathname(); @@ -129,15 +129,15 @@ private function extractDiffsFromFinderResult(FinderResult $finderResult): array // Get the stats for this file $stats = ''; - if (\method_exists($file, 'getStats')) { + if (\method_exists(object_or_class: $file, method: 'getStats')) { $this->logger?->debug('Getting stats from file method'); $stats = $file->getStats(); } else { $this->logger?->debug('Extracting stats from diff content'); // Try to extract stats from the diff content - \preg_match('/^(.*?)(?=diff --git)/s', $diffContent, $matches); + \preg_match(pattern: '/^(.*?)(?=diff --git)/s', subject: $diffContent, matches: $matches); if (!empty($matches[1])) { - $stats = \trim($matches[1]); + $stats = \trim(string: $matches[1]); $this->logger?->debug('Stats extracted from diff content'); } else { $this->logger?->debug('No stats found in diff content'); @@ -152,12 +152,12 @@ private function extractDiffsFromFinderResult(FinderResult $finderResult): array $this->logger?->debug('Diff processed', [ 'file' => $originalPath, - 'diffLength' => \strlen($diffContent), + 'diffLength' => \strlen(string: $diffContent), 'hasStats' => !empty($stats), ]); } - $this->logger?->debug('All diffs extracted', ['diffCount' => \count($diffs)]); + $this->logger?->debug('All diffs extracted', ['diffCount' => \count(value: $diffs)]); return $diffs; } @@ -176,28 +176,28 @@ private function renderOutput(array $diffs, string $treeView, GitDiffSource $sou if (empty($diffs)) { $this->logger?->info('No diffs found for commit range', ['commit' => $source->commit]); $builder - ->addTitle("Git Diff for Commit Range: {$source->commit}", 1) - ->addText("No changes found in this commit range."); + ->addTitle(title: "Git Diff for Commit Range: {$source->commit}") + ->addText(text: "No changes found in this commit range."); return $builder->build(); } $builder - ->addTitle("Git Diff for Commit Range: {$source->commit}", 1) - ->addTitle($source->getDescription(), 2) - ->addTitle("Summary of Changes", 2) - ->addTreeView($treeView); + ->addTitle(title: "Git Diff for Commit Range: {$source->commit}") + ->addTitle(title: $source->getDescription(), level: 2) + ->addTitle(title: "Summary of Changes", level: 2) + ->addTreeView(treeView: $treeView); // Get the appropriate render strategy - $strategy = $this->getRenderStrategy($source->renderConfig->strategy); + $strategy = $this->getRenderStrategy(strategy: $source->renderConfig->strategy); // Use the strategy to render the output $content = $builder - ->merge($strategy->render($diffs, $source->renderConfig)) + ->merge(builder: $strategy->render($diffs, $source->renderConfig)) ->build(); $this->logger?->debug('Output rendered using strategy', [ - 'contentLength' => \strlen($content), + 'contentLength' => \strlen(string: $content), ]); return $content; @@ -218,6 +218,6 @@ private function renderOutput(array $diffs, string $treeView, GitDiffSource $sou */ private function getRenderStrategy(RenderStrategyEnum $strategy): RenderStrategyInterface { - return $this->renderStrategyFactory->create($strategy); + return $this->renderStrategyFactory->create(strategy: $strategy); } } diff --git a/src/Source/GitDiff/RenderStrategy/Config/RenderConfig.php b/src/Source/GitDiff/RenderStrategy/Config/RenderConfig.php index 484c4215..b29f21d1 100644 --- a/src/Source/GitDiff/RenderStrategy/Config/RenderConfig.php +++ b/src/Source/GitDiff/RenderStrategy/Config/RenderConfig.php @@ -28,7 +28,7 @@ public function __construct( public static function fromArray(array $data): self { $strategy = isset($data['strategy']) - ? RenderStrategyEnum::fromString($data['strategy']) + ? RenderStrategyEnum::fromString(value: $data['strategy']) : RenderStrategyEnum::Raw; return new self( @@ -44,7 +44,7 @@ public static function fromArray(array $data): self public static function fromString(string $render): self { return new self( - strategy: RenderStrategyEnum::fromString($render), + strategy: RenderStrategyEnum::fromString(value: $render), showStats: true, contextLines: 3, ); @@ -55,7 +55,7 @@ public static function fromString(string $render): self */ public function jsonSerialize(): array { - return \array_filter([ + return \array_filter(array: [ 'strategy' => $this->strategy->value, 'showStats' => $this->showStats, 'contextLines' => $this->contextLines, diff --git a/src/Source/GitDiff/RenderStrategy/Enum/RenderStrategyEnum.php b/src/Source/GitDiff/RenderStrategy/Enum/RenderStrategyEnum.php index ee7abaed..1d668aa3 100644 --- a/src/Source/GitDiff/RenderStrategy/Enum/RenderStrategyEnum.php +++ b/src/Source/GitDiff/RenderStrategy/Enum/RenderStrategyEnum.php @@ -14,16 +14,16 @@ enum RenderStrategyEnum: string */ public static function fromString(string $value): self { - $normalizedValue = \strtolower(\trim($value)); + $normalizedValue = \strtolower(string: \trim(string: $value)); return match ($normalizedValue) { 'raw' => self::Raw, 'llm' => self::LLM, default => throw new \InvalidArgumentException( - \sprintf( + message: \sprintf( 'Invalid render strategy "%s". Valid strategies are: %s', $value, - \implode(', ', \array_column(self::cases(), 'value')), + \implode(separator: ', ', array: \array_column(array: self::cases(), column_key: 'value')), ), ), }; diff --git a/src/Source/GitDiff/RenderStrategy/LLMFriendlyRenderStrategy.php b/src/Source/GitDiff/RenderStrategy/LLMFriendlyRenderStrategy.php index 2997e670..1598369c 100644 --- a/src/Source/GitDiff/RenderStrategy/LLMFriendlyRenderStrategy.php +++ b/src/Source/GitDiff/RenderStrategy/LLMFriendlyRenderStrategy.php @@ -23,7 +23,7 @@ public function render(array $diffs, RenderConfig $config): ContentBuilder // Handle empty diffs case if (empty($diffs)) { - $builder->addText("No changes found in this commit range."); + $builder->addText(text: "No changes found in this commit range."); return $builder; } @@ -32,16 +32,16 @@ public function render(array $diffs, RenderConfig $config): ContentBuilder // Only show stats if configured to do so if ($config->showStats && !empty($diffData['stats'])) { $builder - ->addTitle("Stats for {$file}", 2) - ->addCodeBlock($diffData['stats']); + ->addTitle(title: "Stats for {$file}", level: 2) + ->addCodeBlock(code: $diffData['stats']); } - $diff = $this->convert($diffData['diff']); + $diff = $this->convert(diff: $diffData['diff']); // Add the enhanced diff $builder - ->addTitle("Diff for {$file}", 2) - ->addCodeBlock($diff, 'diff'); + ->addTitle(title: "Diff for {$file}", level: 2) + ->addCodeBlock(code: $diff, language: 'diff'); } return $builder; @@ -56,44 +56,44 @@ private function convert(string $diff): string return $diff; } - $lines = \explode("\n", $diff); + $lines = \explode(separator: "\n", string: $diff); $enhancedLines = []; $additionBuffer = []; $removalBuffer = []; foreach ($lines as $line) { // Skip diff headers/metadata that start with 'diff', 'index', '---', '+++', or '@@' - if (\str_starts_with($line, 'diff') || - \str_starts_with($line, 'index') || - \str_starts_with($line, '---') || - \str_starts_with($line, '+++') || - \preg_match('/^@@\s+\-\d+,\d+\s+\+\d+,\d+\s+@@/', $line)) { + if (\str_starts_with(haystack: $line, needle: 'diff') || + \str_starts_with(haystack: $line, needle: 'index') || + \str_starts_with(haystack: $line, needle: '---') || + \str_starts_with(haystack: $line, needle: '+++') || + \preg_match(pattern: '/^@@\s+\-\d+,\d+\s+\+\d+,\d+\s+@@/', subject: $line)) { // Output any pending buffers before handling metadata - $this->flushBuffers($enhancedLines, $additionBuffer, $removalBuffer); + $this->flushBuffers(output: $enhancedLines, additionBuffer: $additionBuffer, removalBuffer: $removalBuffer); continue; } // Check for added lines - if (\str_starts_with($line, '+')) { - $additionBuffer[] = \substr($line, 1); // Remove the '+' sign + if (\str_starts_with(haystack: $line, needle: '+')) { + $additionBuffer[] = \substr(string: $line, offset: 1); // Remove the '+' sign continue; } // Check for removed lines - if (\str_starts_with($line, '-')) { - $removalBuffer[] = \substr($line, 1); // Remove the '-' sign + if (\str_starts_with(haystack: $line, needle: '-')) { + $removalBuffer[] = \substr(string: $line, offset: 1); // Remove the '-' sign continue; } // For context lines, flush any pending buffers first - $this->flushBuffers($enhancedLines, $additionBuffer, $removalBuffer); + $this->flushBuffers(output: $enhancedLines, additionBuffer: $additionBuffer, removalBuffer: $removalBuffer); $enhancedLines[] = $line; } // Ensure any remaining buffers are flushed at the end - $this->flushBuffers($enhancedLines, $additionBuffer, $removalBuffer); + $this->flushBuffers(output: $enhancedLines, additionBuffer: $additionBuffer, removalBuffer: $removalBuffer); - return \implode("\n", $enhancedLines); + return \implode(separator: "\n", array: $enhancedLines); } /** diff --git a/src/Source/GitDiff/RenderStrategy/RawRenderStrategy.php b/src/Source/GitDiff/RenderStrategy/RawRenderStrategy.php index f1e072ef..509f4aa4 100644 --- a/src/Source/GitDiff/RenderStrategy/RawRenderStrategy.php +++ b/src/Source/GitDiff/RenderStrategy/RawRenderStrategy.php @@ -24,13 +24,13 @@ public function render(array $diffs, RenderConfig $config): ContentBuilder // Only show stats if configured to do so if ($config->showStats && !empty($diffData['stats'])) { $builder - ->addTitle("Stats for {$file}", 2) - ->addCodeBlock($diffData['stats']); + ->addTitle(title: "Stats for {$file}", level: 2) + ->addCodeBlock(code: $diffData['stats']); } $builder - ->addTitle("Diff for {$file}", 2) - ->addCodeBlock($diffData['diff'], 'diff'); + ->addTitle(title: "Diff for {$file}", level: 2) + ->addCodeBlock(code: $diffData['diff'], language: 'diff'); } return $builder; diff --git a/src/Source/GitDiff/RenderStrategy/RenderStrategyFactory.php b/src/Source/GitDiff/RenderStrategy/RenderStrategyFactory.php index 93d3bc48..8c756253 100644 --- a/src/Source/GitDiff/RenderStrategy/RenderStrategyFactory.php +++ b/src/Source/GitDiff/RenderStrategy/RenderStrategyFactory.php @@ -32,10 +32,10 @@ public function create(RenderStrategyEnum $strategy): RenderStrategyInterface { if (!isset(self::STRATEGIES[$strategy->value])) { throw new \InvalidArgumentException( - \sprintf( + message: \sprintf( 'Invalid render strategy "%s". Valid strategies are: %s', $strategy->value, - \implode(', ', \array_keys(self::STRATEGIES)), + \implode(separator: ', ', array: \array_keys(array: self::STRATEGIES)), ), ); } diff --git a/src/Source/Github/GithubFileInfo.php b/src/Source/Github/GithubFileInfo.php index f9c75962..7bceb627 100644 --- a/src/Source/Github/GithubFileInfo.php +++ b/src/Source/Github/GithubFileInfo.php @@ -41,7 +41,7 @@ public function getContents(): string return $this->fetchedContent; } - return \call_user_func($this->content); + return \call_user_func(callback: $this->content); } /** diff --git a/src/Source/Github/GithubFinder.php b/src/Source/Github/GithubFinder.php index 6a35c24e..b8fd36bb 100644 --- a/src/Source/Github/GithubFinder.php +++ b/src/Source/Github/GithubFinder.php @@ -52,51 +52,51 @@ public function __construct( public function find(FilterableSourceInterface $source, string $basePath = '', array $options = []): FinderResult { if (!$source instanceof GithubSource) { - throw new \InvalidArgumentException('Source must be an instance of GithubSource'); + throw new \InvalidArgumentException(message: 'Source must be an instance of GithubSource'); } if ($source->githubToken) { - $this->githubClient->setToken($this->variableResolver->resolve($source->githubToken)); + $this->githubClient->setToken($this->variableResolver->resolve(strings: $source->githubToken)); } // Parse repository from string - $repository = new GithubRepository($source->repository, $source->branch); + $repository = new GithubRepository(repository: $source->repository, branch: $source->branch); // Initialize path filters based on source configuration - $this->initializePathFilters($source); + $this->initializePathFilters(source: $source); // Get source paths $sourcePaths = $source->sourcePaths; - if (\is_string($sourcePaths)) { + if (\is_string(value: $sourcePaths)) { $sourcePaths = [$sourcePaths]; } // Recursively discover all files from repository paths - $discoveredItems = $this->discoverRepositoryItems($repository, $sourcePaths); + $discoveredItems = $this->discoverRepositoryItems(repository: $repository, sourcePaths: $sourcePaths); // Apply path-based filters - $filteredItems = $this->applyFilters($discoveredItems); + $filteredItems = $this->applyFilters(items: $discoveredItems); // Build result structure $files = []; - $this->buildResultStructure($filteredItems, $repository, $files); + $this->buildResultStructure(items: $filteredItems, repository: $repository, files: $files); // Apply content filters $files = (new ContentsFilter( contains: $source->contains(), notContains: $source->notContains(), - ))->apply($files); + ))->apply(items: $files); // Apply global exclusion registry - $files = $this->applyGlobalExclusions($files); + $files = $this->applyGlobalExclusions(files: $files); /** @psalm-suppress InvalidArgument */ - $tree = \array_map(static fn(GithubFileInfo $file): string => $file->getRelativePathname(), $files); + $tree = \array_map(callback: static fn(GithubFileInfo $file): string => $file->getRelativePathname(), array: $files); // Create the result return new FinderResult( - \array_values($files), - $this->fileTreeBuilder->buildTree($tree, '', $options), + files: \array_values(array: $files), + treeView: $this->fileTreeBuilder->buildTree(files: $tree, basePath: '', options: $options), ); } @@ -117,7 +117,7 @@ public function applyFilters(array $items): array */ private function applyGlobalExclusions(array $files): array { - return \array_filter($files, function (GithubFileInfo $file): bool { + return \array_filter(array: $files, callback: function (GithubFileInfo $file): bool { $path = $file->getRelativePathname(); if ($this->excludeRegistry->shouldExclude($path)) { @@ -144,19 +144,19 @@ private function initializePathFilters(FilterableSourceInterface $source): void // Add file name pattern filter $filePattern = $source->name(); if ($filePattern) { - $this->filters[] = new FilePatternFilter($filePattern); + $this->filters[] = new FilePatternFilter(pattern: $filePattern); } // Add path inclusion filter $path = $source->path(); if ($path) { - $this->filters[] = new PathFilter($path); + $this->filters[] = new PathFilter(pathPattern: $path); } // Add path exclusion filter $excludePatterns = $source->notPath(); if ($excludePatterns) { - $this->filters[] = new ExcludePathFilter($excludePatterns); + $this->filters[] = new ExcludePathFilter(excludePatterns: $excludePatterns); } } @@ -172,8 +172,8 @@ private function discoverRepositoryItems(GithubRepository $repository, array $so $allItems = []; foreach ($sourcePaths as $path) { - $items = $this->fetchDirectoryContents($repository, $path); - $allItems = \array_merge($allItems, $this->traverseDirectoryRecursively($items, $repository)); + $items = $this->fetchDirectoryContents(repository: $repository, path: $path); + $allItems = \array_merge($allItems, $this->traverseDirectoryRecursively(items: $items, repository: $repository)); } return $allItems; @@ -188,8 +188,8 @@ private function traverseDirectoryRecursively(array $items, GithubRepository $re foreach ($items as $item) { if (($item['type'] ?? '') === 'dir') { - $subItems = $this->fetchDirectoryContents($repository, $item['path']); - $result = \array_merge($result, $this->traverseDirectoryRecursively($subItems, $repository)); + $subItems = $this->fetchDirectoryContents(repository: $repository, path: $item['path']); + $result = \array_merge($result, $this->traverseDirectoryRecursively(items: $subItems, repository: $repository)); } else { $result[] = $item; } @@ -210,17 +210,17 @@ private function buildResultStructure( $path = $item['path']; try { - $relativePath = \dirname((string) $path); + $relativePath = \dirname(path: (string) $path); if ($relativePath === '.') { $relativePath = ''; } // Add to files array $files[] = new GithubFileInfo( - $relativePath, - $path, - $item, - fn() => $this->fetchFileContent($repository, $path), + relativePath: $relativePath, + relativePathname: $path, + metadata: $item, + content: fn() => $this->fetchFileContent(repository: $repository, path: $path), ); } catch (\Exception) { // Skip files that can't be processed diff --git a/src/Source/Github/GithubSource.php b/src/Source/Github/GithubSource.php index 1982d012..11d7022c 100644 --- a/src/Source/Github/GithubSource.php +++ b/src/Source/Github/GithubSource.php @@ -100,7 +100,7 @@ public function maxFiles(): int #[\Override] public function jsonSerialize(): array { - return \array_filter([ + return \array_filter(array: [ 'type' => 'github', ...parent::jsonSerialize(), 'repository' => $this->repository, @@ -113,6 +113,6 @@ public function jsonSerialize(): array 'notContains' => $this->notContains, 'showTreeView' => $this->showTreeView, 'githubToken' => $this->githubToken, - ], static fn($value) => $value !== null && (!\is_array($value) || !empty($value))); + ], callback: static fn($value) => $value !== null && (!\is_array(value: $value) || !empty($value))); } } diff --git a/src/Source/Github/GithubSourceBootloader.php b/src/Source/Github/GithubSourceBootloader.php index 3ff66ef4..b1bdf1e1 100644 --- a/src/Source/Github/GithubSourceBootloader.php +++ b/src/Source/Github/GithubSourceBootloader.php @@ -30,7 +30,7 @@ public function init( SourceRegistryInterface $sourceRegistry, GithubSourceFactory $factory, ): void { - $registry->register(GithubSourceFetcher::class); + $registry->register(fetcher: GithubSourceFetcher::class); $sourceRegistry->register($factory); } } diff --git a/src/Source/Github/GithubSourceFactory.php b/src/Source/Github/GithubSourceFactory.php index e43ab1e1..85986bb7 100644 --- a/src/Source/Github/GithubSourceFactory.php +++ b/src/Source/Github/GithubSourceFactory.php @@ -27,28 +27,28 @@ public function create(array $config): SourceInterface ]); if (!isset($config['repository'])) { - throw new \RuntimeException('GitHub source must have a "repository" property'); + throw new \RuntimeException(message: 'GitHub source must have a "repository" property'); } // Determine source paths (required) if (!isset($config['sourcePaths'])) { - throw new \RuntimeException('GitHub source must have a "sourcePaths" property'); + throw new \RuntimeException(message: 'GitHub source must have a "sourcePaths" property'); } $sourcePaths = $config['sourcePaths']; - if (!\is_string($sourcePaths) && !\is_array($sourcePaths)) { - throw new \RuntimeException('"sourcePaths" must be a string or array in source'); + if (!\is_string(value: $sourcePaths) && !\is_array(value: $sourcePaths)) { + throw new \RuntimeException(message: '"sourcePaths" must be a string or array in source'); } // Validate filePattern if present if (isset($config['filePattern'])) { - if (!\is_string($config['filePattern']) && !\is_array($config['filePattern'])) { - throw new \RuntimeException('filePattern must be a string or an array of strings'); + if (!\is_string(value: $config['filePattern']) && !\is_array(value: $config['filePattern'])) { + throw new \RuntimeException(message: 'filePattern must be a string or an array of strings'); } // If it's an array, make sure all elements are strings - if (\is_array($config['filePattern'])) { + if (\is_array(value: $config['filePattern'])) { foreach ($config['filePattern'] as $pattern) { - if (!\is_string($pattern)) { - throw new \RuntimeException('All elements in filePattern must be strings'); + if (!\is_string(value: $pattern)) { + throw new \RuntimeException(message: 'All elements in filePattern must be strings'); } } } diff --git a/src/Source/Github/GithubSourceFetcher.php b/src/Source/Github/GithubSourceFetcher.php index 6beb3396..fd16feab 100644 --- a/src/Source/Github/GithubSourceFetcher.php +++ b/src/Source/Github/GithubSourceFetcher.php @@ -43,7 +43,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $this->logger?->error($errorMessage, [ 'sourceType' => $source::class, ]); - throw new \InvalidArgumentException($errorMessage); + throw new \InvalidArgumentException(message: $errorMessage); } $this->logger?->info('Fetching GitHub source content', [ @@ -58,15 +58,15 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi 'repository' => $source->repository, 'branch' => $source->branch, ]); - $repository = new GithubRepository($source->repository, $source->branch); + $repository = new GithubRepository(repository: $source->repository, branch: $source->branch); // Create builder $this->logger?->debug('Creating content builder'); $builder = $this->builderFactory ->create() - ->addTitle($source->getDescription(), 2) + ->addTitle(title: $source->getDescription(), level: 2) ->addDescription( - \sprintf('Repository: %s. Branch: %s', $repository->getUrl(), $repository->branch), + description: \sprintf('Repository: %s. Branch: %s', $repository->getUrl(), $repository->branch), ); // Find files using the finder and get the FinderResult @@ -74,7 +74,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi 'repository' => $repository->getUrl(), 'branch' => $repository->branch, ]); - $finderResult = $this->finder->find($source); + $finderResult = $this->finder->find(source: $source); $fileCount = $finderResult->count(); $this->logger?->debug('Files found in repository', [ 'fileCount' => $fileCount, @@ -83,7 +83,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi // Add tree view if requested if ($source->showTreeView) { $this->logger?->debug('Adding tree view to output'); - $builder->addTreeView($finderResult->treeView); + $builder->addTreeView(treeView: $finderResult->treeView); } // Fetch and add the content of each file @@ -98,16 +98,16 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $fileContent = $modifiersApplier->apply($file->getContents(), $path); - $language = $this->detectLanguage($path); + $language = $this->detectLanguage(filePath: $path); $this->logger?->debug('Adding file to content', [ 'file' => $path, 'language' => $language, - 'contentLength' => \strlen($fileContent), + 'contentLength' => \strlen(string: $fileContent), ]); $builder ->addCodeBlock( - code: \trim($fileContent), + code: \trim(string: $fileContent), language: $language, path: $path, ); @@ -118,7 +118,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi 'repository' => $repository->getUrl(), 'branch' => $repository->branch, 'fileCount' => $fileCount, - 'contentLength' => \strlen($content), + 'contentLength' => \strlen(string: $content), ]); // Return built content @@ -127,7 +127,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi private function detectLanguage(string $filePath): ?string { - $extension = \pathinfo($filePath, PATHINFO_EXTENSION); + $extension = \pathinfo(path: $filePath, flags: PATHINFO_EXTENSION); $this->logger?->debug('Detecting language for file', [ 'file' => $filePath, diff --git a/src/Source/Gitlab/Config/GitlabServerParserPlugin.php b/src/Source/Gitlab/Config/GitlabServerParserPlugin.php index 608b9edf..7538c586 100644 --- a/src/Source/Gitlab/Config/GitlabServerParserPlugin.php +++ b/src/Source/Gitlab/Config/GitlabServerParserPlugin.php @@ -28,7 +28,7 @@ public function getConfigKey(): string public function supports(array $config): bool { return isset($config['settings']['gitlab']['servers']) - && \is_array($config['settings']['gitlab']['servers']); + && \is_array(value: $config['settings']['gitlab']['servers']); } public function updateConfig(array $config, string $rootPath): array @@ -39,14 +39,14 @@ public function updateConfig(array $config, string $rootPath): array public function parse(array $config, string $rootPath): ?RegistryInterface { - if (!$this->supports($config)) { + if (!$this->supports(config: $config)) { $this->logger?->debug('No GitLab server settings found in configuration'); return null; } $serversConfig = $config['settings']['gitlab']['servers']; $this->logger?->info('Parsing GitLab server configurations', [ - 'serverCount' => \count($serversConfig), + 'serverCount' => \count(value: $serversConfig), ]); foreach ($serversConfig as $name => $serverConfig) { @@ -55,8 +55,8 @@ public function parse(array $config, string $rootPath): ?RegistryInterface 'name' => $name, ]); - $server = ServerConfig::fromArray($serverConfig); - $this->serverRegistry->register($name, $server); + $server = ServerConfig::fromArray(config: $serverConfig); + $this->serverRegistry->register(name: $name, config: $server); $this->logger?->debug('Registered GitLab server', [ 'name' => $name, @@ -70,7 +70,7 @@ public function parse(array $config, string $rootPath): ?RegistryInterface } $this->logger?->info('GitLab server configurations parsed successfully', [ - 'registeredServers' => \count($this->serverRegistry->all()), + 'registeredServers' => \count(value: $this->serverRegistry->all()), ]); return null; diff --git a/src/Source/Gitlab/Config/ServerConfig.php b/src/Source/Gitlab/Config/ServerConfig.php index b1a4a0ce..381e1584 100644 --- a/src/Source/Gitlab/Config/ServerConfig.php +++ b/src/Source/Gitlab/Config/ServerConfig.php @@ -39,7 +39,7 @@ public static function create( public static function fromArray(array $config): self { if (!isset($config['url'])) { - throw new \InvalidArgumentException('GitLab server configuration must have a "url" property'); + throw new \InvalidArgumentException(message: 'GitLab server configuration must have a "url" property'); } return self::create( @@ -51,21 +51,21 @@ public static function fromArray(array $config): self public function withResolvedVariables(VariableResolver $resolver): self { - $resolvedHeaders = \array_map(static fn($value) => $resolver->resolve($value), $this->headers); + $resolvedHeaders = \array_map(callback: static fn($value) => $resolver->resolve(strings: $value), array: $this->headers); return new self( - url: $resolver->resolve($this->url), - token: $this->token !== null ? $resolver->resolve($this->token) : null, + url: $resolver->resolve(strings: $this->url), + token: $this->token !== null ? $resolver->resolve(strings: $this->token) : null, headers: $resolvedHeaders, ); } public function jsonSerialize(): array { - return \array_filter([ + return \array_filter(array: [ 'url' => $this->url, 'token' => $this->token, 'headers' => $this->headers, - ], static fn($value) => $value !== null && (!\is_array($value) || !empty($value))); + ], callback: static fn($value) => $value !== null && (!\is_array(value: $value) || !empty($value))); } } diff --git a/src/Source/Gitlab/Config/ServerRegistry.php b/src/Source/Gitlab/Config/ServerRegistry.php index 37e71ec6..70986857 100644 --- a/src/Source/Gitlab/Config/ServerRegistry.php +++ b/src/Source/Gitlab/Config/ServerRegistry.php @@ -36,8 +36,8 @@ public function has(string $name): bool public function get(string $name): ServerConfig { - if (!$this->has($name)) { - throw new \InvalidArgumentException(\sprintf('GitLab server "%s" not found in registry', $name)); + if (!$this->has(name: $name)) { + throw new \InvalidArgumentException(message: \sprintf('GitLab server "%s" not found in registry', $name)); } return $this->servers[$name]; diff --git a/src/Source/Gitlab/GitlabFileInfo.php b/src/Source/Gitlab/GitlabFileInfo.php index 4318997f..dd5a9181 100644 --- a/src/Source/Gitlab/GitlabFileInfo.php +++ b/src/Source/Gitlab/GitlabFileInfo.php @@ -38,7 +38,7 @@ public function getContents(): string return $this->fetchedContent; } - return $this->fetchedContent = \call_user_func($this->content); + return $this->fetchedContent = \call_user_func(callback: $this->content); } public function getSize(): int diff --git a/src/Source/Gitlab/GitlabFinder.php b/src/Source/Gitlab/GitlabFinder.php index 04433021..1957ac50 100644 --- a/src/Source/Gitlab/GitlabFinder.php +++ b/src/Source/Gitlab/GitlabFinder.php @@ -41,50 +41,50 @@ public function __construct( public function find(FilterableSourceInterface $source, string $basePath = '', array $options = []): FinderResult { if (!$source instanceof GitlabSource) { - throw new \InvalidArgumentException('Source must be an instance of GitlabSource'); + throw new \InvalidArgumentException(message: 'Source must be an instance of GitlabSource'); } // Configure GitLab client based on source configuration - $this->configureGitlabClient($source); + $this->configureGitlabClient(source: $source); // Parse repository from string - $repository = new GitlabRepository($source->repository, $source->branch); + $repository = new GitlabRepository(repository: $source->repository, branch: $source->branch); // Initialize path filters based on source configuration - $this->initializePathFilters($source); + $this->initializePathFilters(source: $source); // Get source paths $sourcePaths = $source->sourcePaths; - if (\is_string($sourcePaths)) { + if (\is_string(value: $sourcePaths)) { $sourcePaths = [$sourcePaths]; } // Recursively discover all files from repository paths - $discoveredItems = $this->discoverRepositoryItems($repository, $sourcePaths); + $discoveredItems = $this->discoverRepositoryItems(repository: $repository, sourcePaths: $sourcePaths); // Apply path-based filters - $filteredItems = $this->applyFilters($discoveredItems); + $filteredItems = $this->applyFilters(items: $discoveredItems); // Build result structure $files = []; - $this->buildResultStructure($filteredItems, $repository, $files); + $this->buildResultStructure(items: $filteredItems, repository: $repository, files: $files); // Apply content filters $files = (new ContentsFilter( contains: $source->contains(), notContains: $source->notContains(), - ))->apply($files); + ))->apply(items: $files); // Apply global exclusion registry - $files = $this->applyGlobalExclusions($files); + $files = $this->applyGlobalExclusions(files: $files); /** @psalm-suppress InvalidArgument */ - $tree = \array_map(static fn(GitlabFileInfo $file): string => $file->getRelativePathname(), $files); + $tree = \array_map(callback: static fn(GitlabFileInfo $file): string => $file->getRelativePathname(), array: $files); // Create the result return new FinderResult( - \array_values($files), - $this->fileTreeBuilder->buildTree($tree, '', $options), + files: \array_values(array: $files), + treeView: $this->fileTreeBuilder->buildTree(files: $tree, basePath: '', options: $options), ); } @@ -102,7 +102,7 @@ public function applyFilters(array $items): array */ private function applyGlobalExclusions(array $files): array { - return \array_filter($files, function (GitlabFileInfo $file): bool { + return \array_filter(array: $files, callback: function (GitlabFileInfo $file): bool { $path = $file->getRelativePathname(); if ($this->excludeRegistry->shouldExclude($path)) { @@ -148,19 +148,19 @@ private function initializePathFilters(FilterableSourceInterface $source): void // Add file name pattern filter $filePattern = $source->name(); if ($filePattern) { - $this->filters[] = new FilePatternFilter($filePattern); + $this->filters[] = new FilePatternFilter(pattern: $filePattern); } // Add path inclusion filter $path = $source->path(); if ($path) { - $this->filters[] = new PathFilter($path); + $this->filters[] = new PathFilter(pathPattern: $path); } // Add path exclusion filter $excludePatterns = $source->notPath(); if ($excludePatterns) { - $this->filters[] = new ExcludePathFilter($excludePatterns); + $this->filters[] = new ExcludePathFilter(excludePatterns: $excludePatterns); } } @@ -176,8 +176,8 @@ private function discoverRepositoryItems(GitlabRepository $repository, array $so $allItems = []; foreach ($sourcePaths as $path) { - $items = $this->fetchDirectoryContents($repository, $path); - $allItems = \array_merge($allItems, $this->traverseDirectoryRecursively($items, $repository)); + $items = $this->fetchDirectoryContents(repository: $repository, path: $path); + $allItems = \array_merge($allItems, $this->traverseDirectoryRecursively(items: $items, repository: $repository)); } return $allItems; @@ -192,8 +192,8 @@ private function traverseDirectoryRecursively(array $items, GitlabRepository $re foreach ($items as $item) { if (($item['type'] ?? '') === 'tree') { - $subItems = $this->fetchDirectoryContents($repository, $item['path']); - $result = \array_merge($result, $this->traverseDirectoryRecursively($subItems, $repository)); + $subItems = $this->fetchDirectoryContents(repository: $repository, path: $item['path']); + $result = \array_merge($result, $this->traverseDirectoryRecursively(items: $subItems, repository: $repository)); } else { $result[] = $item; } @@ -214,17 +214,17 @@ private function buildResultStructure( $path = $item['path']; try { - $relativePath = \dirname((string) $path); + $relativePath = \dirname(path: (string) $path); if ($relativePath === '.') { $relativePath = ''; } // Add to files array $files[] = new GitlabFileInfo( - $relativePath, - $path, - $item, - fn() => $this->fetchFileContent($repository, $path), + relativePath: $relativePath, + relativePathname: $path, + metadata: $item, + content: fn() => $this->fetchFileContent(repository: $repository, path: $path), ); } catch (\Exception) { // Skip files that can't be processed diff --git a/src/Source/Gitlab/GitlabSource.php b/src/Source/Gitlab/GitlabSource.php index 7c2ddca3..97b77b23 100644 --- a/src/Source/Gitlab/GitlabSource.php +++ b/src/Source/Gitlab/GitlabSource.php @@ -105,7 +105,7 @@ public function maxFiles(): int #[\Override] public function jsonSerialize(): array { - return \array_filter([ + return \array_filter(array: [ 'type' => 'gitlab', ...parent::jsonSerialize(), 'repository' => $this->repository, @@ -118,6 +118,6 @@ public function jsonSerialize(): array 'notContains' => $this->notContains, 'showTreeView' => $this->showTreeView, 'server' => $this->server, - ], static fn($value) => $value !== null && (!\is_array($value) || !empty($value))); + ], callback: static fn($value) => $value !== null && (!\is_array(value: $value) || !empty($value))); } } diff --git a/src/Source/Gitlab/GitlabSourceBootloader.php b/src/Source/Gitlab/GitlabSourceBootloader.php index d9d4be22..aa71baa9 100644 --- a/src/Source/Gitlab/GitlabSourceBootloader.php +++ b/src/Source/Gitlab/GitlabSourceBootloader.php @@ -28,7 +28,7 @@ public function init( GitlabSourceFactory $factory, ): void { // Register the GitLab source fetcher with the fetcher registry - $registry->register(GitlabSourceFetcher::class); + $registry->register(fetcher: GitlabSourceFetcher::class); // Register the GitLab source factory with the source registry $sourceRegistry->register($factory); @@ -39,6 +39,6 @@ public function boot( GitlabServerParserPlugin $plugin, ): void { // Register the GitLab server parser plugin with the config loader - $parserRegistry->registerParserPlugin($plugin); + $parserRegistry->registerParserPlugin(plugin: $plugin); } } diff --git a/src/Source/Gitlab/GitlabSourceFactory.php b/src/Source/Gitlab/GitlabSourceFactory.php index bc0ef76c..d61ce0f6 100644 --- a/src/Source/Gitlab/GitlabSourceFactory.php +++ b/src/Source/Gitlab/GitlabSourceFactory.php @@ -38,28 +38,28 @@ public function create(array $config): SourceInterface ]); if (!isset($config['repository'])) { - throw new \RuntimeException('GitLab source must have a "repository" property'); + throw new \RuntimeException(message: 'GitLab source must have a "repository" property'); } // Determine source paths (required) if (!isset($config['sourcePaths'])) { - throw new \RuntimeException('GitLab source must have a "sourcePaths" property'); + throw new \RuntimeException(message: 'GitLab source must have a "sourcePaths" property'); } $sourcePaths = $config['sourcePaths']; - if (!\is_string($sourcePaths) && !\is_array($sourcePaths)) { - throw new \RuntimeException('"sourcePaths" must be a string or array in source'); + if (!\is_string(value: $sourcePaths) && !\is_array(value: $sourcePaths)) { + throw new \RuntimeException(message: '"sourcePaths" must be a string or array in source'); } // Validate filePattern if present if (isset($config['filePattern'])) { - if (!\is_string($config['filePattern']) && !\is_array($config['filePattern'])) { - throw new \RuntimeException('filePattern must be a string or an array of strings'); + if (!\is_string(value: $config['filePattern']) && !\is_array(value: $config['filePattern'])) { + throw new \RuntimeException(message: 'filePattern must be a string or an array of strings'); } // If it's an array, make sure all elements are strings - if (\is_array($config['filePattern'])) { + if (\is_array(value: $config['filePattern'])) { foreach ($config['filePattern'] as $pattern) { - if (!\is_string($pattern)) { - throw new \RuntimeException('All elements in filePattern must be strings'); + if (!\is_string(value: $pattern)) { + throw new \RuntimeException(message: 'All elements in filePattern must be strings'); } } } @@ -73,9 +73,9 @@ public function create(array $config): SourceInterface // Validate server configuration if ($server !== null) { $server = match (true) { - \is_string($server) => $this->serverRegistry->get($server), - \is_array($server) => ServerConfig::fromArray($server), - default => throw new \RuntimeException('GitLab server must be provided'), + \is_string(value: $server) => $this->serverRegistry->get(name: $server), + \is_array(value: $server) => ServerConfig::fromArray(config: $server), + default => throw new \RuntimeException(message: 'GitLab server must be provided'), }; } diff --git a/src/Source/Gitlab/GitlabSourceFetcher.php b/src/Source/Gitlab/GitlabSourceFetcher.php index d6497068..b377e124 100644 --- a/src/Source/Gitlab/GitlabSourceFetcher.php +++ b/src/Source/Gitlab/GitlabSourceFetcher.php @@ -41,7 +41,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $this->logger->error($errorMessage, [ 'sourceType' => $source::class, ]); - throw new \InvalidArgumentException($errorMessage); + throw new \InvalidArgumentException(message: $errorMessage); } $this->logger->info('Fetching GitLab source content', [ @@ -56,23 +56,23 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi 'repository' => $source->repository, 'branch' => $source->branch, ]); - $repository = new GitlabRepository($source->repository, $source->branch); + $repository = new GitlabRepository(repository: $source->repository, branch: $source->branch); // Create builder $this->logger->debug('Creating content builder'); $builder = $this->builderFactory ->create() - ->addTitle($source->getDescription(), 2); + ->addTitle(title: $source->getDescription(), level: 2); if (!$source->server) { - throw new \RuntimeException('GitLab server is not set'); + throw new \RuntimeException(message: 'GitLab server is not set'); } // Determine server URL from source or default $serverUrl = $source->server->url; $builder->addDescription( - \sprintf('Repository: %s. Branch: %s', $repository->getUrl($serverUrl), $repository->branch), + description: \sprintf('Repository: %s. Branch: %s', $repository->getUrl(serverUrl: $serverUrl), $repository->branch), ); // Find files using the finder and get the FinderResult @@ -80,7 +80,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi 'repository' => $repository->getPath(), 'branch' => $repository->branch, ]); - $finderResult = $this->finder->find($source); + $finderResult = $this->finder->find(source: $source); $fileCount = $finderResult->count(); $this->logger->debug('Files found in repository', [ 'fileCount' => $fileCount, @@ -89,7 +89,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi // Add tree view if requested if ($source->showTreeView) { $this->logger->debug('Adding tree view to output'); - $builder->addTreeView($finderResult->treeView); + $builder->addTreeView(treeView: $finderResult->treeView); } // Fetch and add the content of each file @@ -104,16 +104,16 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $fileContent = $modifiersApplier->apply($file->getContents(), $path); - $language = $this->detectLanguage($path); + $language = $this->detectLanguage(filePath: $path); $this->logger->debug('Adding file to content', [ 'file' => $path, 'language' => $language, - 'contentLength' => \strlen($fileContent), + 'contentLength' => \strlen(string: $fileContent), ]); $builder ->addCodeBlock( - code: \trim($fileContent), + code: \trim(string: $fileContent), language: $language, path: $path, ); @@ -124,7 +124,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi 'repository' => $repository->getPath(), 'branch' => $repository->branch, 'fileCount' => $fileCount, - 'contentLength' => \strlen($content), + 'contentLength' => \strlen(string: $content), ]); // Return built content @@ -136,7 +136,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi */ private function detectLanguage(string $filePath): ?string { - $extension = \pathinfo($filePath, PATHINFO_EXTENSION); + $extension = \pathinfo(path: $filePath, flags: PATHINFO_EXTENSION); $this->logger->debug('Detecting language for file', [ 'file' => $filePath, diff --git a/src/Source/Registry/AbstractSourceFactory.php b/src/Source/Registry/AbstractSourceFactory.php index a73670df..2b78a62a 100644 --- a/src/Source/Registry/AbstractSourceFactory.php +++ b/src/Source/Registry/AbstractSourceFactory.php @@ -27,6 +27,6 @@ public function __construct( */ protected function parseModifiers(array $modifiersConfig): array { - return $this->modifierResolver->resolveAll($modifiersConfig); + return $this->modifierResolver->resolveAll(references: $modifiersConfig); } } diff --git a/src/Source/Registry/SourceRegistry.php b/src/Source/Registry/SourceRegistry.php index 2433fd3e..118cea06 100644 --- a/src/Source/Registry/SourceRegistry.php +++ b/src/Source/Registry/SourceRegistry.php @@ -37,7 +37,7 @@ public function register(SourceFactoryInterface $factory): self public function create(string $type, array $config): SourceInterface { if (!isset($this->factories[$type])) { - throw new \RuntimeException(\sprintf('Source factory for type "%s" not found', $type)); + throw new \RuntimeException(message: \sprintf('Source factory for type "%s" not found', $type)); } $factory = $this->factories[$type]; diff --git a/src/Source/Text/TextSource.php b/src/Source/Text/TextSource.php index 64ebd587..0d7a3ed7 100644 --- a/src/Source/Text/TextSource.php +++ b/src/Source/Text/TextSource.php @@ -28,11 +28,11 @@ public function __construct( #[\Override] public function jsonSerialize(): array { - return \array_filter([ + return \array_filter(array: [ 'type' => 'text', ...parent::jsonSerialize(), 'content' => $this->content, 'tag' => $this->tag, - ], static fn($value) => $value !== null && $value !== '' && $value !== []); + ], callback: static fn($value) => $value !== null && $value !== '' && $value !== []); } } diff --git a/src/Source/Text/TextSourceBootloader.php b/src/Source/Text/TextSourceBootloader.php index 551dfa95..e55558c5 100644 --- a/src/Source/Text/TextSourceBootloader.php +++ b/src/Source/Text/TextSourceBootloader.php @@ -23,7 +23,7 @@ public function init( SourceRegistryInterface $sourceRegistry, TextSourceFactory $factory, ): void { - $registry->register(TextSourceFetcher::class); + $registry->register(fetcher: TextSourceFetcher::class); $sourceRegistry->register($factory); } } diff --git a/src/Source/Text/TextSourceFactory.php b/src/Source/Text/TextSourceFactory.php index 7615b479..51b9b2a5 100644 --- a/src/Source/Text/TextSourceFactory.php +++ b/src/Source/Text/TextSourceFactory.php @@ -25,8 +25,8 @@ public function create(array $config): SourceInterface 'config' => $config, ]); - if (!isset($config['content']) || !\is_string($config['content'])) { - throw new \RuntimeException('Text source must have a "content" string property'); + if (!isset($config['content']) || !\is_string(value: $config['content'])) { + throw new \RuntimeException(message: 'Text source must have a "content" string property'); } return new TextSource( diff --git a/src/Source/Text/TextSourceFetcher.php b/src/Source/Text/TextSourceFetcher.php index 0f699868..bea959ac 100644 --- a/src/Source/Text/TextSourceFetcher.php +++ b/src/Source/Text/TextSourceFetcher.php @@ -43,37 +43,37 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $this->logger?->error($errorMessage, [ 'sourceType' => $source::class, ]); - throw new \InvalidArgumentException($errorMessage); + throw new \InvalidArgumentException(message: $errorMessage); } - $description = $this->variableResolver->resolve($source->getDescription()); + $description = $this->variableResolver->resolve(strings: $source->getDescription()); $this->logger?->info('Fetching text source content', [ 'description' => $description, 'tag' => $source->tag, - 'contentLength' => \strlen($source->content), + 'contentLength' => \strlen(string: $source->content), ]); // Create builder $this->logger?->debug('Creating content builder'); $builder = $this->builderFactory ->create() - ->addDescription($description); + ->addDescription(description: $description); $this->logger?->debug('Adding text content with tags', [ 'tag' => $source->tag, ]); - $content = $this->variableResolver->resolve($source->content); - $tag = $this->variableResolver->resolve($source->tag); + $content = $this->variableResolver->resolve(strings: $source->content); + $tag = $this->variableResolver->resolve(strings: $source->tag); $builder - ->addBlock(new TextBlock($modifiersApplier->apply($content, 'file.txt'), $tag)) + ->addBlock(block: new TextBlock(content: $modifiersApplier->apply($content, 'file.txt'), tag: $tag)) ->addSeparator(); $content = $builder->build(); $this->logger?->info('Text source content fetched successfully', [ - 'contentLength' => \strlen($content), + 'contentLength' => \strlen(string: $content), ]); // Return built content diff --git a/src/Source/Tree/TreeSource.php b/src/Source/Tree/TreeSource.php index 1f4bbe94..8ab9a508 100644 --- a/src/Source/Tree/TreeSource.php +++ b/src/Source/Tree/TreeSource.php @@ -80,7 +80,7 @@ public function in(): array|null $directories = []; foreach ((array) $this->sourcePaths as $path) { - if (\is_dir($path)) { + if (\is_dir(filename: $path)) { $directories[] = $path; } } @@ -93,7 +93,7 @@ public function files(): array|null $files = []; foreach ((array) $this->sourcePaths as $path) { - if (\is_file($path)) { + if (\is_file(filename: $path)) { $files[] = $path; } } @@ -141,6 +141,6 @@ public function jsonSerialize(): array $result['dirContext'] = $this->dirContext; } - return \array_filter($result); + return \array_filter(array: $result); } } diff --git a/src/Source/Tree/TreeSourceBootloader.php b/src/Source/Tree/TreeSourceBootloader.php index 5eb8e186..2005fe3c 100644 --- a/src/Source/Tree/TreeSourceBootloader.php +++ b/src/Source/Tree/TreeSourceBootloader.php @@ -30,7 +30,7 @@ public function init( SourceRegistryInterface $sourceRegistry, TreeSourceFactory $factory, ): void { - $registry->register(TreeSourceFetcher::class); + $registry->register(fetcher: TreeSourceFetcher::class); $sourceRegistry->register($factory); } } diff --git a/src/Source/Tree/TreeSourceFactory.php b/src/Source/Tree/TreeSourceFactory.php index a8386abc..1bc142e9 100644 --- a/src/Source/Tree/TreeSourceFactory.php +++ b/src/Source/Tree/TreeSourceFactory.php @@ -29,31 +29,31 @@ public function create(array $config): SourceInterface if (!isset($config['sourcePaths'])) { - throw new \RuntimeException('Tree source must have a "sourcePaths" property'); + throw new \RuntimeException(message: 'Tree source must have a "sourcePaths" property'); } $sourcePaths = $config['sourcePaths']; - if (!\is_string($sourcePaths) && !\is_array($sourcePaths)) { - throw new \RuntimeException('"sourcePaths" must be a string or array in source'); + if (!\is_string(value: $sourcePaths) && !\is_array(value: $sourcePaths)) { + throw new \RuntimeException(message: '"sourcePaths" must be a string or array in source'); } - $sourcePaths = \is_string($sourcePaths) ? [$sourcePaths] : $sourcePaths; + $sourcePaths = \is_string(value: $sourcePaths) ? [$sourcePaths] : $sourcePaths; $sourcePaths = \array_map( - fn(string $sourcePaths): string => (string) $this->dirs->getRootPath()->join($sourcePaths), - $sourcePaths, + callback: fn(string $sourcePaths): string => (string) $this->dirs->getRootPath()->join($sourcePaths), + array: $sourcePaths, ); // Validate filePattern if present if (isset($config['filePattern'])) { - if (!\is_string($config['filePattern']) && !\is_array($config['filePattern'])) { - throw new \RuntimeException('filePattern must be a string or an array of strings'); + if (!\is_string(value: $config['filePattern']) && !\is_array(value: $config['filePattern'])) { + throw new \RuntimeException(message: 'filePattern must be a string or an array of strings'); } // If it's an array, make sure all elements are strings - if (\is_array($config['filePattern'])) { + if (\is_array(value: $config['filePattern'])) { foreach ($config['filePattern'] as $pattern) { - if (!\is_string($pattern)) { - throw new \RuntimeException('All elements in filePattern must be strings'); + if (!\is_string(value: $pattern)) { + throw new \RuntimeException(message: 'All elements in filePattern must be strings'); } } } @@ -61,17 +61,17 @@ public function create(array $config): SourceInterface // Validate renderFormat if present if (isset($config['renderFormat'])) { - if (!\is_string($config['renderFormat'])) { - throw new \RuntimeException('renderFormat must be a string'); + if (!\is_string(value: $config['renderFormat'])) { + throw new \RuntimeException(message: 'renderFormat must be a string'); } $validFormats = ['ascii']; - if (!\in_array($config['renderFormat'], $validFormats, true)) { + if (!\in_array(needle: $config['renderFormat'], haystack: $validFormats, strict: true)) { throw new \RuntimeException( - \sprintf( + message: \sprintf( 'Invalid renderFormat: %s. Allowed formats: %s', $config['renderFormat'], - \implode(', ', $validFormats), + \implode(separator: ', ', array: $validFormats), ), ); } @@ -84,8 +84,8 @@ public function create(array $config): SourceInterface $notPath = $config['notPath'] ?? []; // Validate dirContext if present - if (isset($config['dirContext']) && !\is_array($config['dirContext'])) { - throw new \RuntimeException('dirContext must be an associative array'); + if (isset($config['dirContext']) && !\is_array(value: $config['dirContext'])) { + throw new \RuntimeException(message: 'dirContext must be an associative array'); } return new TreeSource( diff --git a/src/Source/Tree/TreeSourceFetcher.php b/src/Source/Tree/TreeSourceFetcher.php index e37a3c90..4c526c10 100644 --- a/src/Source/Tree/TreeSourceFetcher.php +++ b/src/Source/Tree/TreeSourceFetcher.php @@ -43,7 +43,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $this->logger?->error($errorMessage, [ 'sourceType' => $source::class, ]); - throw new \InvalidArgumentException($errorMessage); + throw new \InvalidArgumentException(message: $errorMessage); } $this->logger?->info('Fetching tree source content', [ @@ -57,14 +57,14 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $this->logger?->debug('Creating content builder'); $builder = $this->builderFactory ->create() - ->addTitle($source->getDescription()); + ->addTitle(title: $source->getDescription()); try { // Use SymfonyFinder to find files - $finderResult = $this->finder->find($source, $this->basePath, $source->treeView->getOptions()); + $finderResult = $this->finder->find(source: $source, basePath: $this->basePath, options: $source->treeView->getOptions()); // Add content to builder - $builder->addCodeBlock($finderResult->treeView); + $builder->addCodeBlock(code: $finderResult->treeView); } catch (\Throwable $e) { $errorMessage = \sprintf('Error while generating tree: %s', $e->getMessage()); $this->logger?->error($errorMessage, [ @@ -72,12 +72,12 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi 'file' => $e->getFile(), 'line' => $e->getLine(), ]); - throw new \RuntimeException($errorMessage); + throw new \RuntimeException(message: $errorMessage); } $content = $builder->build(); $this->logger?->info('Tree source content fetched successfully', [ - 'contentLength' => \strlen($content), + 'contentLength' => \strlen(string: $content), ]); return $content; diff --git a/src/Source/Url/UrlSource.php b/src/Source/Url/UrlSource.php index a2e09a9e..380a83c4 100644 --- a/src/Source/Url/UrlSource.php +++ b/src/Source/Url/UrlSource.php @@ -40,18 +40,18 @@ public function getSelector(): ?string */ public function hasSelector(): bool { - return $this->selector !== null && \trim($this->selector) !== ''; + return $this->selector !== null && \trim(string: $this->selector) !== ''; } #[\Override] public function jsonSerialize(): array { - return \array_filter([ + return \array_filter(array: [ 'type' => 'url', ...parent::jsonSerialize(), 'urls' => $this->urls, 'selector' => $this->getSelector(), 'headers' => $this->headers, - ], static fn($value) => $value !== null && $value !== '' && $value !== []); + ], callback: static fn($value) => $value !== null && $value !== '' && $value !== []); } } diff --git a/src/Source/Url/UrlSourceBootloader.php b/src/Source/Url/UrlSourceBootloader.php index e8a8eed2..b285dc30 100644 --- a/src/Source/Url/UrlSourceBootloader.php +++ b/src/Source/Url/UrlSourceBootloader.php @@ -47,7 +47,7 @@ public function init( SourceRegistryInterface $sourceRegistry, UrlSourceFactory $factory, ): void { - $registry->register(UrlSourceFetcher::class); + $registry->register(fetcher: UrlSourceFetcher::class); $sourceRegistry->register($factory); } } diff --git a/src/Source/Url/UrlSourceFactory.php b/src/Source/Url/UrlSourceFactory.php index 5431dff5..629d1336 100644 --- a/src/Source/Url/UrlSourceFactory.php +++ b/src/Source/Url/UrlSourceFactory.php @@ -26,13 +26,13 @@ public function create(array $config): UrlSource ]); - if (!isset($config['urls']) || !\is_array($config['urls'])) { - throw new \RuntimeException('URL source must have a "urls" array property'); + if (!isset($config['urls']) || !\is_array(value: $config['urls'])) { + throw new \RuntimeException(message: 'URL source must have a "urls" array property'); } // Add headers validation and parsing $headers = []; - if (isset($config['headers']) && \is_array($config['headers'])) { + if (isset($config['headers']) && \is_array(value: $config['headers'])) { $headers = $config['headers']; } diff --git a/src/Source/Url/UrlSourceFetcher.php b/src/Source/Url/UrlSourceFetcher.php index 666d1120..309a42bb 100644 --- a/src/Source/Url/UrlSourceFetcher.php +++ b/src/Source/Url/UrlSourceFetcher.php @@ -58,31 +58,31 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi $this->logger?->error($errorMessage, [ 'sourceType' => $source::class, ]); - throw new \InvalidArgumentException($errorMessage); + throw new \InvalidArgumentException(message: $errorMessage); } $this->logger?->info('Fetching URL source content', [ - 'urlCount' => \count($source->urls), + 'urlCount' => \count(value: $source->urls), 'hasSelector' => $source->hasSelector(), ]); // Create builder $builder = $this->builderFactory ->create() - ->addDescription($this->variableResolver->resolve($source->getDescription())); + ->addDescription(description: $this->variableResolver->resolve(strings: $source->getDescription())); foreach ($source->urls as $index => $url) { - $url = $this->variableResolver->resolve($url); + $url = $this->variableResolver->resolve(strings: $url); $this->logger?->debug('Processing URL', [ 'url' => $url, 'index' => $index + 1, - 'total' => \count($source->urls), + 'total' => \count(value: $source->urls), ]); try { $requestHeaders = $this->variableResolver->resolve( - \array_merge($this->defaultHeaders, $source->headers), + strings: \array_merge($this->defaultHeaders, $source->headers), ); // Send the request @@ -101,8 +101,8 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi ]); $builder - ->addComment("URL: {$url}") - ->addComment("Error: HTTP status code {$statusCode}") + ->addComment(comment: "URL: {$url}") + ->addComment(comment: "Error: HTTP status code {$statusCode}") ->addSeparator(); continue; } @@ -114,7 +114,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi // Get the response body $html = $response->getBody(); - $htmlLength = \strlen($html); + $htmlLength = \strlen(string: $html); $this->logger?->debug('Received HTML content', [ 'url' => $url, 'contentLength' => $htmlLength, @@ -123,7 +123,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi // Extract content from specific selector if defined if ($source->hasSelector() && $this->selectorExtractor !== null) { $selector = $source->getSelector(); - \assert(!empty($selector)); + \assert(assertion: !empty($selector)); $this->logger?->debug('Extracting content using selector', [ 'url' => $url, @@ -131,7 +131,7 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi ]); $contentFromSelector = $this->selectorExtractor->extract($html, $selector); - $extractedLength = \strlen($contentFromSelector); + $extractedLength = \strlen(string: $contentFromSelector); if (empty($contentFromSelector)) { $this->logger?->warning('Selector did not match any content', [ @@ -140,8 +140,8 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi ]); $builder - ->addComment("URL: {$url}") - ->addComment("Warning: Selector '{$source->getSelector()}' didn't match any content") + ->addComment(comment: "URL: {$url}") + ->addComment(comment: "Warning: Selector '{$source->getSelector()}' didn't match any content") ->addSeparator(); } else { $this->logger?->debug('Content extracted using selector', [ @@ -151,26 +151,26 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi 'originalLength' => $htmlLength, ]); - $builder->addComment("URL: {$url} (selector: {$source->getSelector()})"); + $builder->addComment(comment: "URL: {$url} (selector: {$source->getSelector()})"); $html = $contentFromSelector; } } else { // Process the whole page $this->logger?->debug('Processing entire HTML page', ['url' => $url]); - $builder->addComment("URL: {$url}"); + $builder->addComment(comment: "URL: {$url}"); } $this->logger?->debug('Cleaning HTML content', ['url' => $url]); $cleanedHtml = $modifiersApplier->apply($this->cleaner->clean($html), $url); $this->logger?->debug('HTML content cleaned', [ 'url' => $url, - 'originalLength' => \strlen($html), - 'cleanedLength' => \strlen($cleanedHtml), + 'originalLength' => \strlen(string: $html), + 'cleanedLength' => \strlen(string: $cleanedHtml), ]); $builder - ->addText($cleanedHtml) - ->addComment("END OF URL: {$url}") + ->addText(text: $cleanedHtml) + ->addComment(comment: "END OF URL: {$url}") ->addSeparator(); $this->logger?->debug('URL processed successfully', ['url' => $url]); @@ -183,16 +183,16 @@ public function fetch(SourceInterface $source, ModifiersApplierInterface $modifi ]); $builder - ->addComment("URL: {$url}") - ->addComment("Error: {$e->getMessage()}") + ->addComment(comment: "URL: {$url}") + ->addComment(comment: "Error: {$e->getMessage()}") ->addSeparator(); } } $content = $builder->build(); $this->logger?->info('URL source content fetched successfully', [ - 'contentLength' => \strlen($content), - 'urlCount' => \count($source->urls), + 'contentLength' => \strlen(string: $content), + 'urlCount' => \count(value: $source->urls), ]); // Return built content diff --git a/tests/src/AppTestCase.php b/tests/src/AppTestCase.php index 4587e8c9..7f94b1d3 100644 --- a/tests/src/AppTestCase.php +++ b/tests/src/AppTestCase.php @@ -25,7 +25,7 @@ public function defineDirectories(string $root): array public function rootDirectory(): string { - return \dirname(__DIR__); + return \dirname(path: __DIR__); } public function getApp(): TestableKernelInterface @@ -53,7 +53,7 @@ public function createAppInstance(Container $container = new Container()): Testa */ public function makeApp(array $env = [], Container $container = new Container()): Kernel&TestableKernelInterface { - $environment = new Environment($env); + $environment = new Environment(values: $env); $app = $this->createAppInstance($container); $app->run($environment); @@ -64,8 +64,8 @@ public function makeApp(array $env = [], Container $container = new Container()) public function initApp(array $env = [], Container $container = new Container()): Kernel&TestableKernelInterface { $container->bindSingleton( - Application::class, - new Application( + alias: Application::class, + resolver: new Application( version: '1.0.0', name: 'Context Generator', isBinary: true, @@ -87,7 +87,7 @@ public function getContainer(): Container */ public function get(string $id): mixed { - return $this->getApp()->getContainer()->get($id); + return $this->getApp()->getContainer()->get(id: $id); } protected function setUp(): void diff --git a/tests/src/Feature/Compiler/AbstractCompilerTestCase.php b/tests/src/Feature/Compiler/AbstractCompilerTestCase.php index 7163d12f..295cf10a 100644 --- a/tests/src/Feature/Compiler/AbstractCompilerTestCase.php +++ b/tests/src/Feature/Compiler/AbstractCompilerTestCase.php @@ -17,7 +17,7 @@ protected function assertConfigItems(DocumentCompiler $compiler, ConfigRegistryA foreach ($config->getDocuments() as $document) { $outputPaths[] = $this->getContextsDir($document->outputPath); - $compiledDocument = $compiler->compile($document); + $compiledDocument = $compiler->compile(document: $document); $results[$document->outputPath] = (string) $compiledDocument->content; } @@ -29,7 +29,7 @@ protected function assertConfigItems(DocumentCompiler $compiler, ConfigRegistryA $this->assertSame( <<<'CONTENT' # Project structure - ### + ### ``` └── src/ [309.0 B, 309 chars] └── dir1/ [217.0 B, 217 chars] @@ -42,7 +42,7 @@ protected function assertConfigItems(DocumentCompiler $compiler, ConfigRegistryA └── dir2/ [92.0 B, 92 chars] └── Test2Class.php [85.0 B, 85 chars] └── file.txt [7.0 B, 7 chars] - + ``` CONTENT, $results['structure.md'], @@ -59,37 +59,37 @@ protected function assertConfigItems(DocumentCompiler $compiler, ConfigRegistryA └── TestClass.php └── subdir1/ └── Test3Class.php - + ``` ### Path: `/src/dir1/Test1Class.php` - + ```php Foo Bar @@ -107,19 +107,19 @@ protected function assertConfigItems(DocumentCompiler $compiler, ConfigRegistryA └── src/ └── dir2/ └── Test2Class.php - + ``` ### Path: `/src/dir2/Test2Class.php` - + ```php Foo Bar @@ -141,20 +141,20 @@ protected function assertConfigItems(DocumentCompiler $compiler, ConfigRegistryA │ └── file.txt └── dir2/ └── file.txt - + ``` ### Path: `/src/dir1/file.txt` - + ```txt foo baf ``` ### Path: `/src/dir1/subdir1/file.txt` - + ```txt foo bar ``` ### Path: `/src/dir2/file.txt` - + ```txt foo baz ``` diff --git a/tests/src/Feature/Console/GenerateCommand/CompilingResult.php b/tests/src/Feature/Console/GenerateCommand/CompilingResult.php index 1a289285..5ec36cfc 100644 --- a/tests/src/Feature/Console/GenerateCommand/CompilingResult.php +++ b/tests/src/Feature/Console/GenerateCommand/CompilingResult.php @@ -112,7 +112,7 @@ public function assertContext(string $document, array $contains = [], array $not $contextPath = $documentData['output_path'] . '/' . $documentData['context_path'], ); - $content = \file_get_contents($contextPath); + $content = \file_get_contents(filename: $contextPath); foreach ($contains as $string) { TestCase::assertStringContainsString( $string, @@ -195,7 +195,7 @@ public function assertDocumentError(string $document, array $contains): self foreach ($contains as $string) { TestCase::assertStringContainsString( $string, - \implode("\n", $documentData['errors']), + \implode(separator: "\n", array: $documentData['errors']), \sprintf( 'Document [%s] does not contain error [%s]', $documentData['context_path'], diff --git a/tests/src/Feature/Console/GenerateCommand/ContextBuilder.php b/tests/src/Feature/Console/GenerateCommand/ContextBuilder.php index b3b3d1a1..31dedc4f 100644 --- a/tests/src/Feature/Console/GenerateCommand/ContextBuilder.php +++ b/tests/src/Feature/Console/GenerateCommand/ContextBuilder.php @@ -51,14 +51,14 @@ public function build( args: $args, ); - $output = \trim($output); - $data = \json_decode($output, true); + $output = \trim(string: $output); + $data = \json_decode(json: $output, associative: true); if (!$data) { - throw new \RuntimeException('Failed to decode JSON output: ' . \json_last_error_msg()); + throw new \RuntimeException(message: 'Failed to decode JSON output: ' . \json_last_error_msg()); } - return new CompilingResult($data); + return new CompilingResult(result: $data); } private function runCommand( @@ -67,13 +67,13 @@ private function runCommand( ?OutputInterface $output = null, ?int $verbosityLevel = null, ): string { - $input = new ArrayInput($args); - $input->setInteractive(false); + $input = new ArrayInput(parameters: $args); + $input->setInteractive(interactive: false); $output ??= new BufferedOutput(); /** @psalm-suppress ArgumentTypeCoercion */ $output->setVerbosity($verbosityLevel ?? $this->defaultVerbosityLevel); - $this->console->run($command, $input, $output); + $this->console->run(command: $command, input: $input, output: $output); return $output->fetch(); } diff --git a/tests/src/Feature/Console/GenerateCommand/ExcludeTest.php b/tests/src/Feature/Console/GenerateCommand/ExcludeTest.php index 5f34296e..a7e489a1 100644 --- a/tests/src/Feature/Console/GenerateCommand/ExcludeTest.php +++ b/tests/src/Feature/Console/GenerateCommand/ExcludeTest.php @@ -91,7 +91,7 @@ protected function buildContext( string $command = 'generate', bool $asJson = true, ): CompilingResult { - return (new ContextBuilder($this->getConsole()))->build( + return (new ContextBuilder(console: $this->getConsole()))->build( workDir: $workDir, configPath: $configPath, inlineJson: $inlineJson, diff --git a/tests/src/Feature/Console/GenerateCommand/FileSourceTest.php b/tests/src/Feature/Console/GenerateCommand/FileSourceTest.php index 16367500..11bf996c 100644 --- a/tests/src/Feature/Console/GenerateCommand/FileSourceTest.php +++ b/tests/src/Feature/Console/GenerateCommand/FileSourceTest.php @@ -162,7 +162,7 @@ protected function buildContext( string $command = 'generate', bool $asJson = true, ): CompilingResult { - return (new ContextBuilder($this->getConsole()))->build( + return (new ContextBuilder(console: $this->getConsole()))->build( workDir: $workDir, configPath: $configPath, inlineJson: $inlineJson, diff --git a/tests/src/Feature/Console/GenerateCommand/GenerateCommandTest.php b/tests/src/Feature/Console/GenerateCommand/GenerateCommandTest.php index 81839054..19f31e09 100644 --- a/tests/src/Feature/Console/GenerateCommand/GenerateCommandTest.php +++ b/tests/src/Feature/Console/GenerateCommand/GenerateCommandTest.php @@ -134,7 +134,7 @@ public function json_config_should_be_rendered(): void #[DataProvider('commandsProvider')] public function inline_json_should_be_used_instead_of_file(): void { - $inlineJson = \file_get_contents($this->getFixturesDir('Console/GenerateCommand/inline-json.json')); + $inlineJson = \file_get_contents(filename: $this->getFixturesDir('Console/GenerateCommand/inline-json.json')); $this ->buildContext( @@ -272,7 +272,7 @@ protected function buildContext( string $command = 'generate', bool $asJson = true, ): CompilingResult { - return (new ContextBuilder($this->getConsole()))->build( + return (new ContextBuilder(console: $this->getConsole()))->build( workDir: $workDir, configPath: $configPath, inlineJson: $inlineJson, diff --git a/tests/src/Feature/Console/GenerateCommand/GithubSourceTest.php b/tests/src/Feature/Console/GenerateCommand/GithubSourceTest.php index eaceded0..030a2b8d 100644 --- a/tests/src/Feature/Console/GenerateCommand/GithubSourceTest.php +++ b/tests/src/Feature/Console/GenerateCommand/GithubSourceTest.php @@ -386,7 +386,7 @@ protected function setUp(): void $this->mockGithubClient = new MockGithubClient(); // Register mock GitHub client in the container - $this->getContainer()->bindSingleton(GithubClientInterface::class, $this->mockGithubClient); + $this->getContainer()->bindSingleton(alias: GithubClientInterface::class, resolver: $this->mockGithubClient); } protected function buildContext( @@ -397,7 +397,7 @@ protected function buildContext( string $command = 'generate', bool $asJson = true, ): CompilingResult { - return (new ContextBuilder($this->getConsole()))->build( + return (new ContextBuilder(console: $this->getConsole()))->build( workDir: $workDir, configPath: $configPath, inlineJson: $inlineJson, diff --git a/tests/src/Feature/Console/GenerateCommand/GitlabSourceTest.php b/tests/src/Feature/Console/GenerateCommand/GitlabSourceTest.php index 2702b61d..4ef69ab5 100644 --- a/tests/src/Feature/Console/GenerateCommand/GitlabSourceTest.php +++ b/tests/src/Feature/Console/GenerateCommand/GitlabSourceTest.php @@ -461,7 +461,7 @@ protected function setUp(): void $this->mockGitlabClient = new MockGitlabClient(); // Register mock GitLab client in the container - $this->getContainer()->bindSingleton(GitlabClientInterface::class, $this->mockGitlabClient); + $this->getContainer()->bindSingleton(alias: GitlabClientInterface::class, resolver: $this->mockGitlabClient); } protected function buildContext( @@ -472,7 +472,7 @@ protected function buildContext( string $command = 'generate', bool $asJson = true, ): CompilingResult { - return (new ContextBuilder($this->getConsole()))->build( + return (new ContextBuilder(console: $this->getConsole()))->build( workDir: $workDir, configPath: $configPath, inlineJson: $inlineJson, diff --git a/tests/src/Feature/Console/GenerateCommand/LocalImportTest.php b/tests/src/Feature/Console/GenerateCommand/LocalImportTest.php index ecfde49f..572d8160 100644 --- a/tests/src/Feature/Console/GenerateCommand/LocalImportTest.php +++ b/tests/src/Feature/Console/GenerateCommand/LocalImportTest.php @@ -44,7 +44,7 @@ public function basic_local_import_should_be_rendered(string $command): void import: - path: {$this->getRelativePath($baseConfig)} type: local - + documents: - description: "Main Document" outputPath: "main.md" @@ -110,8 +110,8 @@ public function local_import_with_path_prefix_should_be_applied(string $command) import: - path: {$this->getRelativePath($baseConfig)} type: local - pathPrefix: "prefixed" - + pathPrefix: "prefixed" + documents: - description: "Main Document" outputPath: "main.md" @@ -194,7 +194,7 @@ public function local_import_with_selective_documents_should_work(string $comman docs: - "first.md" - "third.md" - + documents: - description: "Main Document" outputPath: "main.md" @@ -273,7 +273,7 @@ public function nested_local_imports_should_be_processed(string $command): void import: - path: {$this->getRelativePath($nestedConfig)} type: local - + documents: - description: "Middle Document" outputPath: "middle.md" @@ -292,7 +292,7 @@ public function nested_local_imports_should_be_processed(string $command): void import: - path: {$this->getRelativePath($middleConfig)} type: local - + documents: - description: "Main Document" outputPath: "main.md" @@ -363,7 +363,7 @@ public function circular_imports_should_be_detected(string $command): void import: - path: {$this->getRelativePath($firstConfig)} type: local - + documents: - description: "Second Document" outputPath: "second.md" @@ -378,12 +378,12 @@ public function circular_imports_should_be_detected(string $command): void // Now update the first config to import the second \file_put_contents( - $firstConfig, - <<getRelativePath($secondConfig)} type: local - + documents: - description: "First Document" outputPath: "first.md" @@ -448,7 +448,7 @@ public function wildcard_imports_should_be_processed(string $command): void import: - path: {$this->getRelativePath($wildcardDir)}/*.yaml type: local - + documents: - description: "Main Document" outputPath: "main.md" @@ -507,7 +507,7 @@ public function variables_from_imported_configs_should_be_merged(string $command variables: BASE_VAR: "base-variable-value" SHARED_VAR: "base-shared-value" - + documents: - description: "Base Variable Document" outputPath: "base-vars.md" @@ -526,11 +526,11 @@ public function variables_from_imported_configs_should_be_merged(string $command import: - path: {$this->getRelativePath($baseConfig)} type: local - + variables: MAIN_VAR: "main-variable-value" SHARED_VAR: "main-shared-value" # This should override the imported one - + documents: - description: "Main Variable Document" outputPath: "main-vars.md" @@ -592,7 +592,7 @@ protected function buildContext( string $command = 'generate', bool $asJson = true, ): CompilingResult { - return (new ContextBuilder($this->getConsole()))->build( + return (new ContextBuilder(console: $this->getConsole()))->build( workDir: $workDir, configPath: $configPath, inlineJson: $inlineJson, @@ -606,6 +606,6 @@ private function getRelativePath(string $absolutePath): string { // Convert absolute path to relative path for use in YAML configurations // This ensures the test is independent of the absolute paths on the test system - return \basename($absolutePath); + return \basename(path: $absolutePath); } } diff --git a/tests/src/Feature/Console/GenerateCommand/MockGithubClient.php b/tests/src/Feature/Console/GenerateCommand/MockGithubClient.php index e180acfd..e9162cf3 100644 --- a/tests/src/Feature/Console/GenerateCommand/MockGithubClient.php +++ b/tests/src/Feature/Console/GenerateCommand/MockGithubClient.php @@ -35,7 +35,7 @@ public function getFileContent(GithubRepository $repository, string $path): stri return $this->fileContents[$repoKey][$path]; } - throw new \RuntimeException("File content not found for {$path} in repository {$repository->repository}"); + throw new \RuntimeException(message: "File content not found for {$path} in repository {$repository->repository}"); } public function setToken(?string $token): void @@ -45,7 +45,7 @@ public function setToken(?string $token): void public function getReleaseManager(GithubRepository $repository): ReleaseManager { - throw new \RuntimeException('ReleaseManager is not implemented in this mock'); + throw new \RuntimeException(message: 'ReleaseManager is not implemented in this mock'); } /** diff --git a/tests/src/Feature/Console/GenerateCommand/MockGitlabClient.php b/tests/src/Feature/Console/GenerateCommand/MockGitlabClient.php index b6785966..997bc03b 100644 --- a/tests/src/Feature/Console/GenerateCommand/MockGitlabClient.php +++ b/tests/src/Feature/Console/GenerateCommand/MockGitlabClient.php @@ -40,7 +40,7 @@ public function getFileContent(GitlabRepository $repository, string $path): stri return $this->fileContents[$repoKey][$path]; } - throw new \RuntimeException("File content not found for {$path} in repository {$repository->repository}"); + throw new \RuntimeException(message: "File content not found for {$path} in repository {$repository->repository}"); } public function setToken(?string $token): void diff --git a/tests/src/Feature/Console/GenerateCommand/MockHttpClient.php b/tests/src/Feature/Console/GenerateCommand/MockHttpClient.php index 6cd15124..63049576 100644 --- a/tests/src/Feature/Console/GenerateCommand/MockHttpClient.php +++ b/tests/src/Feature/Console/GenerateCommand/MockHttpClient.php @@ -41,7 +41,7 @@ public function post(string $url, array $headers = [], ?string $body = null): Ht public function getWithRedirects(string $url, array $headers = []): HttpResponse { - return $this->get($url, $headers); + return $this->get(url: $url, headers: $headers); } public function addResponse(string $url, HttpResponse $response): void diff --git a/tests/src/Feature/Console/GenerateCommand/PromptAssertions.php b/tests/src/Feature/Console/GenerateCommand/PromptAssertions.php index c16d0362..2c3a6f44 100644 --- a/tests/src/Feature/Console/GenerateCommand/PromptAssertions.php +++ b/tests/src/Feature/Console/GenerateCommand/PromptAssertions.php @@ -94,7 +94,7 @@ public function assertPromptMessages(string $id, array $messageContents): self foreach ($prompt['messages'] as $message) { if (isset($message['content']['text'])) { $messagesContent .= $message['content']['text'] . "\n"; - } elseif (\is_string($message['content'])) { + } elseif (\is_string(value: $message['content'])) { $messagesContent .= $message['content'] . "\n"; } } @@ -249,7 +249,7 @@ public function assertPromptSchema(string $id, array $properties = [], array $re \sprintf('Schema for prompt [%s] does not have property [%s]', $id, $propName), ); - if (\is_array($propData)) { + if (\is_array(value: $propData)) { foreach ($propData as $key => $value) { TestCase::assertArrayHasKey( $key, @@ -307,7 +307,7 @@ public function assertPromptCount(int $count): self TestCase::assertCount( $count, $this->result['prompts'] ?? [], - \sprintf('Expected %d prompts, got %d', $count, \count($this->result['prompts'] ?? [])), + \sprintf('Expected %d prompts, got %d', $count, \count(value: $this->result['prompts'] ?? [])), ); return $this; diff --git a/tests/src/Feature/Console/GenerateCommand/PromptValidationTest.php b/tests/src/Feature/Console/GenerateCommand/PromptValidationTest.php index e08f1f98..16e22792 100644 --- a/tests/src/Feature/Console/GenerateCommand/PromptValidationTest.php +++ b/tests/src/Feature/Console/GenerateCommand/PromptValidationTest.php @@ -46,7 +46,7 @@ public function prompt_without_messages_or_extensions_should_be_invalid(string $ // For now, check that the prompt count is 0 // If the implementation doesn't reject empty prompts, this test may need adjustment - $result->assertPromptCount(0); + $result->assertPromptCount(count: 0); } #[Test] @@ -71,7 +71,7 @@ public function prompt_with_empty_messages_array_should_be_invalid(string $comma ); // The implementation should reject a prompt with empty messages array - $result->assertPromptCount(0); + $result->assertPromptCount(count: 0); } #[Test] @@ -97,7 +97,7 @@ public function prompt_with_invalid_message_format_should_be_rejected(string $co ); // The implementation should reject a prompt with invalid message format - $result->assertPromptCount(0); + $result->assertPromptCount(count: 0); } #[Test] @@ -124,7 +124,7 @@ public function prompt_with_missing_message_content_should_be_rejected(string $c ); // The implementation should reject a prompt with missing message content - $result->assertPromptCount(0); + $result->assertPromptCount(count: 0); } #[Test] @@ -151,7 +151,7 @@ public function prompt_with_missing_message_role_should_be_rejected(string $comm ); // The implementation should reject a prompt with missing message role - $result->assertPromptCount(0); + $result->assertPromptCount(count: 0); } #[Test] @@ -178,7 +178,7 @@ public function prompt_with_invalid_message_role_should_be_rejected(string $comm ); // The implementation should reject a prompt with invalid message role - $result->assertPromptCount(0); + $result->assertPromptCount(count: 0); } #[Test] @@ -206,7 +206,7 @@ public function prompt_extending_non_existent_template_should_be_rejected(string ); // The implementation should reject a prompt extending a non-existent template - $result->assertPromptCount(0); + $result->assertPromptCount(count: 0); } #[Test] @@ -221,7 +221,7 @@ public function template_without_messages_should_be_invalid(string $command): vo type: template description: "Template with no messages" # Missing 'messages' - + - id: extending-empty description: "Prompt extending empty template" extend: @@ -243,7 +243,7 @@ public function template_without_messages_should_be_invalid(string $command): vo // 2. Or warn about the empty template // For now, check that no valid prompts are compiled - $result->assertPromptCount(0); + $result->assertPromptCount(count: 0); } #[Test] @@ -259,7 +259,7 @@ public function prompt_with_invalid_extension_format_should_be_rejected(string $ messages: - role: user content: "Template content" - + - id: invalid-extension description: "Prompt with invalid extension format" extend: @@ -318,7 +318,7 @@ public function prompt_with_missing_id_should_be_rejected(string $command): void ); // The implementation should reject a prompt with no ID - $result->assertPromptCount(0); + $result->assertPromptCount(count: 0); } #[Test] @@ -345,7 +345,7 @@ public function prompt_with_empty_id_should_be_rejected(string $command): void ); // The implementation should reject a prompt with an empty ID - $result->assertPromptCount(0); + $result->assertPromptCount(count: 0); } #[Test] @@ -361,7 +361,7 @@ public function duplicated_prompt_ids_should_be_resolved(string $command): void messages: - role: user content: "First prompt content" - + - id: duplicate-id description: "Second prompt with the same ID" messages: @@ -379,8 +379,8 @@ public function duplicated_prompt_ids_should_be_resolved(string $command): void // The implementation should handle duplicate IDs (either by warning or by overwriting) // Expect that only one prompt with this ID exists in the output - $result->assertPromptCount(1); - $result->assertPromptExists('duplicate-id'); + $result->assertPromptCount(count: 1); + $result->assertPromptExists(id: 'duplicate-id'); // Check which version was kept (likely the last one) $rawResult = $result->getResult(); @@ -393,7 +393,7 @@ public function duplicated_prompt_ids_should_be_resolved(string $command): void $content = ""; if (isset($prompt['messages'][0]['content']['text'])) { $content = $prompt['messages'][0]['content']['text']; - } elseif (isset($prompt['messages'][0]['content']) && \is_string($prompt['messages'][0]['content'])) { + } elseif (isset($prompt['messages'][0]['content']) && \is_string(value: $prompt['messages'][0]['content'])) { $content = $prompt['messages'][0]['content']; } $this->assertStringContainsString( @@ -420,7 +420,7 @@ public function prompt_with_both_messages_and_extensions_should_be_valid(string messages: - role: user content: "Template content with {{var}}." - + - id: valid-combined description: "Prompt with both messages and extensions" extend: @@ -441,12 +441,12 @@ public function prompt_with_both_messages_and_extensions_should_be_valid(string ); // The implementation should accept a prompt with both messages and extensions - $result->assertPromptCount(1); - $result->assertPromptExists('valid-combined'); - $result->assertPromptExtends('valid-combined', 'base-template'); + $result->assertPromptCount(count: 1); + $result->assertPromptExists(id: 'valid-combined'); + $result->assertPromptExtends(id: 'valid-combined', templateId: 'base-template'); // Check that both the template content and additional messages are present - $result->assertPromptMessages('valid-combined', [ + $result->assertPromptMessages(id: 'valid-combined', messageContents: [ 'Template content with template variable.', 'Additional message content', ]); @@ -469,7 +469,7 @@ public function circular_template_inheritance_should_be_detected(string $command messages: - role: user content: "Template A content" - + - id: template-b type: template extend: @@ -510,7 +510,7 @@ protected function buildContext( string $command = 'generate', bool $asJson = true, ): CompilingResult { - return (new ContextBuilder($this->getConsole()))->build( + return (new ContextBuilder(console: $this->getConsole()))->build( workDir: $workDir, configPath: $configPath, inlineJson: $inlineJson, diff --git a/tests/src/Feature/Console/GenerateCommand/PromptsTest.php b/tests/src/Feature/Console/GenerateCommand/PromptsTest.php index c0d371a4..afe3adc7 100644 --- a/tests/src/Feature/Console/GenerateCommand/PromptsTest.php +++ b/tests/src/Feature/Console/GenerateCommand/PromptsTest.php @@ -49,20 +49,20 @@ public function basic_prompts_should_be_compiled(string $command): void command: $command, ) ->assertSuccess() - ->assertPromptExists('test-prompt') - ->assertPrompt('test-prompt', [ + ->assertPromptExists(id: 'test-prompt') + ->assertPrompt(id: 'test-prompt', properties: [ 'type' => 'prompt', 'description' => 'A simple test prompt', ]) - ->assertPromptMessages('test-prompt', [ + ->assertPromptMessages(id: 'test-prompt', messageContents: [ 'Hello {{name}}, this is a test prompt.', ]) ->assertPromptSchema( - 'test-prompt', - [ + id: 'test-prompt', + properties: [ 'name' => ['description' => "User's name"], ], - ['name'], + required: ['name'], ); } @@ -85,7 +85,7 @@ public function multiple_prompts_should_be_compiled(string $command): void messages: - role: user content: "Hello {{name}}, this is the first prompt." - + - id: second-prompt description: "Second test prompt" schema: @@ -108,14 +108,14 @@ public function multiple_prompts_should_be_compiled(string $command): void command: $command, ) ->assertSuccess() - ->assertPromptCount(2) - ->assertPromptExists('first-prompt') - ->assertPromptExists('second-prompt') - ->assertPrompt('first-prompt', [ + ->assertPromptCount(count: 2) + ->assertPromptExists(id: 'first-prompt') + ->assertPromptExists(id: 'second-prompt') + ->assertPrompt(id: 'first-prompt', properties: [ 'type' => 'prompt', 'description' => 'First test prompt', ]) - ->assertPrompt('second-prompt', [ + ->assertPrompt(id: 'second-prompt', properties: [ 'type' => 'prompt', 'description' => 'Second test prompt', ]); @@ -134,7 +134,7 @@ public function prompt_templates_should_be_compiled(string $command): void messages: - role: user content: "This is a base template with {{variable}}." - + - id: extended-prompt type: prompt description: "Prompt that extends a template" @@ -162,25 +162,25 @@ public function prompt_templates_should_be_compiled(string $command): void command: $command, ) ->assertSuccess() - ->assertPromptExists('extended-prompt') - ->assertPrompt('extended-prompt', [ + ->assertPromptExists(id: 'extended-prompt') + ->assertPrompt(id: 'extended-prompt', properties: [ 'type' => 'prompt', 'description' => 'Prompt that extends a template', ]) - ->assertPromptExtends('extended-prompt', 'base-template') - ->assertPromptTemplateArguments('extended-prompt', 'base-template', [ + ->assertPromptExtends(id: 'extended-prompt', templateId: 'base-template') + ->assertPromptTemplateArguments(id: 'extended-prompt', templateId: 'base-template', arguments: [ 'variable' => 'custom value', ]) - ->assertPromptMessages('extended-prompt', [ + ->assertPromptMessages(id: 'extended-prompt', messageContents: [ 'This is a base template with custom value.', 'Additional message with {{additionalVar}}.', ]) ->assertPromptSchema( - 'extended-prompt', - [ + id: 'extended-prompt', + properties: [ 'additionalVar' => ['description' => 'Additional parameter'], ], - ['additionalVar'], + required: ['additionalVar'], ); } @@ -197,7 +197,7 @@ public function complex_prompt_inheritance_should_be_compiled(string $command): messages: - role: user content: "Base content with {{baseVar}}." - + - id: intermediate-template type: template extend: @@ -207,7 +207,7 @@ public function complex_prompt_inheritance_should_be_compiled(string $command): messages: - role: user content: "Intermediate content with {{intermediateVar}}." - + - id: final-prompt type: prompt description: "Multi-level inherited prompt" @@ -229,12 +229,12 @@ public function complex_prompt_inheritance_should_be_compiled(string $command): command: $command, ) ->assertSuccess() - ->assertPromptExists('final-prompt') - ->assertPromptExtends('final-prompt', 'intermediate-template') - ->assertPromptTemplateArguments('final-prompt', 'intermediate-template', [ + ->assertPromptExists(id: 'final-prompt') + ->assertPromptExtends(id: 'final-prompt', templateId: 'intermediate-template') + ->assertPromptTemplateArguments(id: 'final-prompt', templateId: 'intermediate-template', arguments: [ 'intermediateVar' => 'final value', ]) - ->assertPromptMessages('final-prompt', [ + ->assertPromptMessages(id: 'final-prompt', messageContents: [ 'Base content with final value.', 'Intermediate content with final value.', 'Final content.', @@ -278,16 +278,16 @@ public function prompt_with_complex_schema_should_be_compiled(string $command): command: $command, ) ->assertSuccess() - ->assertPromptExists('complex-schema-prompt') + ->assertPromptExists(id: 'complex-schema-prompt') ->assertPromptSchema( - 'complex-schema-prompt', - [ + id: 'complex-schema-prompt', + properties: [ 'title' => ['description' => 'Document title'], 'sections' => ['description' => 'Document sections'], 'author' => ['description' => 'Document author'], 'tags' => ['description' => 'Document tags'], ], - ['title', 'author'], + required: ['title', 'author'], ); } @@ -305,7 +305,7 @@ public function prompts_with_tags_should_be_compiled(string $command): void messages: - role: user content: "Help me with coding." - + - id: writing-prompt description: "Writing assistant prompt" tags: ["writing", "content", "creativity"] @@ -361,7 +361,7 @@ public function imported_prompts_should_be_compiled(string $command): void messages: - role: user content: "This template was imported from another file with {{importedVar}}." - + - id: imported-prompt description: "Imported standalone prompt" schema: @@ -383,7 +383,7 @@ public function imported_prompts_should_be_compiled(string $command): void import: - path: {$this->getRelativePath($basePromptsFile)} type: local - + prompts: - id: main-prompt description: "Main file prompt" @@ -406,14 +406,14 @@ public function imported_prompts_should_be_compiled(string $command): void ) ->assertSuccess() ->assertImported(path: $this->getRelativePath($basePromptsFile), type: 'local') - ->assertPromptCount(2) // Only prompts, not templates, should be counted - ->assertPromptExists('imported-prompt') - ->assertPromptExists('main-prompt') - ->assertPromptExtends('main-prompt', 'imported-template') - ->assertPromptTemplateArguments('main-prompt', 'imported-template', [ + ->assertPromptCount(count: 2) // Only prompts, not templates, should be counted + ->assertPromptExists(id: 'imported-prompt') + ->assertPromptExists(id: 'main-prompt') + ->assertPromptExtends(id: 'main-prompt', templateId: 'imported-template') + ->assertPromptTemplateArguments(id: 'main-prompt', templateId: 'imported-template', arguments: [ 'importedVar' => 'successfully imported value', ]) - ->assertPromptMessages('main-prompt', [ + ->assertPromptMessages(id: 'main-prompt', messageContents: [ 'This template was imported from another file with successfully imported value.', 'Additional content from main file.', ]); @@ -433,14 +433,14 @@ public function imported_prompts_with_filter_should_be_compiled(string $command) messages: - role: user content: "I need help with coding." - + - id: design-helper description: "Helps with design tasks" tags: ["design", "ui"] messages: - role: user content: "I need help with design." - + - id: advanced-coding description: "Advanced coding assistance" tags: ["coding", "advanced"] @@ -461,7 +461,7 @@ public function imported_prompts_with_filter_should_be_compiled(string $command) tags: include: ["coding"] exclude: ["advanced"] - + prompts: - id: local-prompt description: "Local prompt" @@ -481,11 +481,11 @@ public function imported_prompts_with_filter_should_be_compiled(string $command) ->assertSuccess() ->assertImported(path: $this->getRelativePath($promptsFile), type: 'local') ->assertPromptCount( - 2, + count: 2, ) // Local prompt + coding-helper (design-helper and advanced-coding should be filtered out) - ->assertPromptExists('coding-helper') - ->assertPromptExists('local-prompt') - ->assertPrompt('coding-helper', [ + ->assertPromptExists(id: 'coding-helper') + ->assertPromptExists(id: 'local-prompt') + ->assertPrompt(id: 'coding-helper', properties: [ 'description' => 'Helps with coding tasks', ]); } @@ -503,13 +503,13 @@ public function imported_prompts_with_ids_filter_should_be_compiled(string $comm messages: - role: user content: "This is the first prompt." - + - id: prompt-two description: "Second prompt" messages: - role: user content: "This is the second prompt." - + - id: prompt-three description: "Third prompt" messages: @@ -527,7 +527,7 @@ public function imported_prompts_with_ids_filter_should_be_compiled(string $comm type: local filter: ids: ["prompt-one", "prompt-three"] - + prompts: - id: local-prompt description: "Local prompt" @@ -546,10 +546,10 @@ public function imported_prompts_with_ids_filter_should_be_compiled(string $comm ) ->assertSuccess() ->assertImported(path: $this->getRelativePath($promptsFile), type: 'local') - ->assertPromptCount(3) // Local prompt + prompt-one + prompt-three - ->assertPromptExists('prompt-one') - ->assertPromptExists('prompt-three') - ->assertPromptExists('local-prompt'); + ->assertPromptCount(count: 3) // Local prompt + prompt-one + prompt-three + ->assertPromptExists(id: 'prompt-one') + ->assertPromptExists(id: 'prompt-three') + ->assertPromptExists(id: 'local-prompt'); } #[Test] @@ -575,7 +575,7 @@ public function invalid_prompt_should_report_error(string $command): void ); // At minimum, the prompt count should be 0 - $result->assertPromptCount(0); + $result->assertPromptCount(count: 0); } #[\Override] @@ -593,7 +593,7 @@ protected function buildContext( string $command = 'generate', bool $asJson = true, ): CompilingResult { - return (new ContextBuilder($this->getConsole()))->build( + return (new ContextBuilder(console: $this->getConsole()))->build( workDir: $workDir, configPath: $configPath, inlineJson: $inlineJson, @@ -607,6 +607,6 @@ private function getRelativePath(string $absolutePath): string { // Convert absolute path to relative path for use in YAML configurations // This ensures the test is independent of the absolute paths on the test system - return \basename($absolutePath); + return \basename(path: $absolutePath); } } diff --git a/tests/src/Feature/Console/GenerateCommand/ToolAssertions.php b/tests/src/Feature/Console/GenerateCommand/ToolAssertions.php index b67cdd98..54c1aa09 100644 --- a/tests/src/Feature/Console/GenerateCommand/ToolAssertions.php +++ b/tests/src/Feature/Console/GenerateCommand/ToolAssertions.php @@ -111,7 +111,7 @@ public function assertToolSchema(string $id, array $properties = [], array $requ \sprintf('Schema for tool [%s] does not have property [%s]', $id, $propName), ); - if (\is_array($propDef)) { + if (\is_array(value: $propDef)) { foreach ($propDef as $key => $value) { TestCase::assertArrayHasKey( $key, @@ -180,13 +180,13 @@ public function assertToolCommands(string $id, array $expectedCommands): self TestCase::assertArrayHasKey('commands', $tool, \sprintf('Tool [%s] does not have commands', $id)); TestCase::assertCount( - \count($expectedCommands), + \count(value: $expectedCommands), $tool['commands'], \sprintf( 'Tool [%s] has %d commands, expected %d', $id, - \count($tool['commands']), - \count($expectedCommands), + \count(value: $tool['commands']), + \count(value: $expectedCommands), ), ); @@ -207,21 +207,21 @@ public function assertToolCommands(string $id, array $expectedCommands): self ); } - if (isset($expectedCommand['args']) && \is_array($expectedCommand['args'])) { + if (isset($expectedCommand['args']) && \is_array(value: $expectedCommand['args'])) { TestCase::assertCount( - \count($expectedCommand['args']), + \count(value: $expectedCommand['args']), $actualCommand['args'], \sprintf( 'Tool [%s] command at index [%d] has %d args, expected %d', $id, $index, - \count($actualCommand['args']), - \count($expectedCommand['args']), + \count(value: $actualCommand['args']), + \count(value: $expectedCommand['args']), ), ); foreach ($expectedCommand['args'] as $argIndex => $expectedArg) { - if (\is_string($expectedArg)) { + if (\is_string(value: $expectedArg)) { TestCase::assertEquals( $expectedArg, $actualCommand['args'][$argIndex], @@ -262,13 +262,13 @@ public function assertToolRequests(string $id, array $expectedRequests): self TestCase::assertArrayHasKey('requests', $tool, \sprintf('Tool [%s] does not have requests', $id)); TestCase::assertCount( - \count($expectedRequests), + \count(value: $expectedRequests), $tool['requests'], \sprintf( 'Tool [%s] has %d requests, expected %d', $id, - \count($tool['requests']), - \count($expectedRequests), + \count(value: $tool['requests']), + \count(value: $expectedRequests), ), ); @@ -297,7 +297,7 @@ public function assertToolRequests(string $id, array $expectedRequests): self ); } - if (isset($expectedRequest['headers']) && \is_array($expectedRequest['headers'])) { + if (isset($expectedRequest['headers']) && \is_array(value: $expectedRequest['headers'])) { foreach ($expectedRequest['headers'] as $headerName => $expectedValue) { TestCase::assertArrayHasKey( $headerName, @@ -338,7 +338,7 @@ public function assertToolCount(int $count): self TestCase::assertCount( $count, $this->result['tools'] ?? [], - \sprintf('Expected %d tools, got %d', $count, \count($this->result['tools'] ?? [])), + \sprintf('Expected %d tools, got %d', $count, \count(value: $this->result['tools'] ?? [])), ); return $this; diff --git a/tests/src/Feature/Console/GenerateCommand/ToolsTest.php b/tests/src/Feature/Console/GenerateCommand/ToolsTest.php index 7d21cbba..4e42a9f1 100644 --- a/tests/src/Feature/Console/GenerateCommand/ToolsTest.php +++ b/tests/src/Feature/Console/GenerateCommand/ToolsTest.php @@ -59,22 +59,22 @@ public function basic_run_tool_should_be_configured(string $command): void command: $command, ) ->assertSuccess() - ->assertToolExists('test-command') - ->assertTool('test-command', [ + ->assertToolExists(id: 'test-command') + ->assertTool(id: 'test-command', properties: [ 'type' => 'run', 'description' => 'A simple test command tool', ]) ->assertToolSchema( - 'test-command', - [ + id: 'test-command', + properties: [ 'param' => [ 'type' => 'string', 'description' => 'Command parameter', ], ], - ['param'], + required: ['param'], ) - ->assertToolCommands('test-command', [ + ->assertToolCommands(id: 'test-command', expectedCommands: [ [ 'cmd' => 'echo', 'args' => ['Hello', '{{param}}'], @@ -122,14 +122,14 @@ public function http_tool_should_be_configured(string $command): void command: $command, ) ->assertSuccess() - ->assertToolExists('test-api') - ->assertTool('test-api', [ + ->assertToolExists(id: 'test-api') + ->assertTool(id: 'test-api', properties: [ 'type' => 'http', 'description' => 'A simple HTTP API tool', ]) ->assertToolSchema( - 'test-api', - [ + id: 'test-api', + properties: [ 'token' => [ 'type' => 'string', 'description' => 'API token', @@ -139,7 +139,7 @@ public function http_tool_should_be_configured(string $command): void 'description' => 'Search query', ], ], - ['token'], + required: ['token'], ); } @@ -158,7 +158,7 @@ public function multiple_tools_should_be_configured(string $command): void - cmd: "ls" args: - "-la" - + - id: api-tool description: "API interaction tool" type: "http" @@ -176,14 +176,14 @@ public function multiple_tools_should_be_configured(string $command): void command: $command, ) ->assertSuccess() - ->assertToolCount(2) - ->assertToolExists('command-tool') - ->assertToolExists('api-tool') - ->assertTool('command-tool', [ + ->assertToolCount(count: 2) + ->assertToolExists(id: 'command-tool') + ->assertToolExists(id: 'api-tool') + ->assertTool(id: 'command-tool', properties: [ 'type' => 'run', 'description' => 'Command execution tool', ]) - ->assertTool('api-tool', [ + ->assertTool(id: 'api-tool', properties: [ 'type' => 'http', 'description' => 'API interaction tool', ]); @@ -227,14 +227,14 @@ public function tool_with_conditional_arguments_should_be_configured(string $com command: $command, ) ->assertSuccess() - ->assertToolExists('conditional-args') - ->assertTool('conditional-args', [ + ->assertToolExists(id: 'conditional-args') + ->assertTool(id: 'conditional-args', properties: [ 'type' => 'run', 'description' => 'Tool with conditional arguments', ]) ->assertToolSchema( - 'conditional-args', - [ + id: 'conditional-args', + properties: [ 'debug' => [ 'type' => 'boolean', 'description' => 'Enable debug mode', @@ -278,8 +278,8 @@ public function tool_with_environment_variables_should_be_configured(string $com command: $command, ) ->assertSuccess() - ->assertToolExists('env-vars-tool') - ->assertTool('env-vars-tool', [ + ->assertToolExists(id: 'env-vars-tool') + ->assertTool(id: 'env-vars-tool', properties: [ 'type' => 'run', 'description' => 'Tool with environment variables', 'env' => [ @@ -339,10 +339,10 @@ enum: ["error", "warning", "info", "debug"] command: $command, ) ->assertSuccess() - ->assertToolExists('complex-schema-tool') + ->assertToolExists(id: 'complex-schema-tool') ->assertToolSchema( - 'complex-schema-tool', - [ + id: 'complex-schema-tool', + properties: [ 'name' => [ 'type' => 'string', 'description' => 'Project name', @@ -353,7 +353,7 @@ enum: ["error", "warning", "info", "debug"] 'default' => '1.0.0', ], ], - ['name'], + required: ['name'], ); } @@ -382,7 +382,7 @@ public function tool_should_be_imported(string $command): void import: - path: {$this->getRelativePath($baseConfig)} type: local - + tools: - id: local-tool description: "Tool defined in main config" @@ -403,9 +403,9 @@ public function tool_should_be_imported(string $command): void ) ->assertSuccess() ->assertImported(path: $this->getRelativePath($baseConfig), type: 'local') - ->assertToolExists('imported-tool') - ->assertToolExists('local-tool') - ->assertToolCount(2); + ->assertToolExists(id: 'imported-tool') + ->assertToolExists(id: 'local-tool') + ->assertToolCount(count: 2); } #[Test] @@ -432,7 +432,7 @@ public function invalid_tool_should_be_reported(string $command): void command: $command, ) ->assertSuccess() - ->assertToolCount(0); + ->assertToolCount(count: 0); } #[\Override] @@ -450,7 +450,7 @@ protected function buildContext( string $command = 'generate', bool $asJson = true, ): CompilingResult { - return (new ContextBuilder($this->getConsole()))->build( + return (new ContextBuilder(console: $this->getConsole()))->build( workDir: $workDir, configPath: $configPath, inlineJson: $inlineJson, @@ -464,6 +464,6 @@ private function getRelativePath(string $absolutePath): string { // Convert absolute path to relative path for use in YAML configurations // This ensures the test is independent of the absolute paths on the test system - return \basename($absolutePath); + return \basename(path: $absolutePath); } } diff --git a/tests/src/Feature/Console/GenerateCommand/UrlImportTest.php b/tests/src/Feature/Console/GenerateCommand/UrlImportTest.php index 4598dd72..1a9590a0 100644 --- a/tests/src/Feature/Console/GenerateCommand/UrlImportTest.php +++ b/tests/src/Feature/Console/GenerateCommand/UrlImportTest.php @@ -27,7 +27,7 @@ public static function commandsProvider(): \Generator public function basic_url_import_should_be_rendered(string $command): void { // Setup mock response for URL import - $jsonConfig = \json_encode([ + $jsonConfig = \json_encode(value: [ 'documents' => [ [ 'description' => 'URL Imported Document', @@ -45,8 +45,8 @@ public function basic_url_import_should_be_rendered(string $command): void ]); $this->mockHttpClient->addResponse( - 'https://example.com/config.json', - new HttpResponse( + url: 'https://example.com/config.json', + response: new HttpResponse( statusCode: 200, body: $jsonConfig, headers: ['Content-Type' => 'application/json'], @@ -59,7 +59,7 @@ public function basic_url_import_should_be_rendered(string $command): void import: - url: https://example.com/config.json type: url - + documents: - description: "Main Document" outputPath: "main.md" @@ -116,8 +116,8 @@ public function url_import_with_headers_should_be_processed(): void YAML; $this->mockHttpClient->addResponse( - 'https://api.example.com/config', - new HttpResponse( + url: 'https://api.example.com/config', + response: new HttpResponse( statusCode: 200, body: $yamlConfig, headers: ['Content-Type' => 'application/yaml'], @@ -133,7 +133,7 @@ public function url_import_with_headers_should_be_processed(): void headers: Authorization: "Bearer test-token" Accept: "application/yaml" - + documents: - description: "Main Document" outputPath: "main.md" @@ -163,7 +163,7 @@ public function url_import_with_headers_should_be_processed(): void ); // Verify the headers were sent correctly - $sentHeaders = $this->mockHttpClient->getRequestHeaders('https://api.example.com/config'); + $sentHeaders = $this->mockHttpClient->getRequestHeaders(url: 'https://api.example.com/config'); $this->assertArrayHasKey('Authorization', $sentHeaders); $this->assertEquals('Bearer test-token', $sentHeaders['Authorization']); $this->assertArrayHasKey('Accept', $sentHeaders); @@ -175,7 +175,7 @@ public function url_import_with_headers_should_be_processed(): void public function url_import_with_variables_should_resolve_variables(): void { // Setup mock response - $jsonConfig = \json_encode([ + $jsonConfig = \json_encode(value: [ 'documents' => [ [ 'description' => 'Variable Test Document', @@ -193,8 +193,8 @@ public function url_import_with_variables_should_resolve_variables(): void ]); $this->mockHttpClient->addResponse( - 'https://api.testing.example.com/config', - new HttpResponse( + url: 'https://api.testing.example.com/config', + response: new HttpResponse( statusCode: 200, body: $jsonConfig, headers: ['Content-Type' => 'application/json'], @@ -215,7 +215,7 @@ public function url_import_with_variables_should_resolve_variables(): void type: url headers: Authorization: "Bearer ${API_TOKEN}" - + documents: - description: "Main Document" outputPath: "main.md" @@ -255,7 +255,7 @@ public function url_import_with_variables_should_resolve_variables(): void ); // Verify the headers were sent with resolved variables - $sentHeaders = $this->mockHttpClient->getRequestHeaders('https://api.testing.example.com/config'); + $sentHeaders = $this->mockHttpClient->getRequestHeaders(url: 'https://api.testing.example.com/config'); $this->assertArrayHasKey('Authorization', $sentHeaders); $this->assertEquals('Bearer test-token', $sentHeaders['Authorization']); } @@ -291,8 +291,8 @@ public function url_import_with_selective_documents_should_work(): void YAML; $this->mockHttpClient->addResponse( - 'https://example.com/multi-docs.yaml', - new HttpResponse( + url: 'https://example.com/multi-docs.yaml', + response: new HttpResponse( statusCode: 200, body: $yamlConfig, headers: ['Content-Type' => 'application/yaml'], @@ -308,7 +308,7 @@ public function url_import_with_selective_documents_should_work(): void docs: - "first.md" - "third.md" - + documents: - description: "Main Document" outputPath: "main.md" @@ -366,8 +366,8 @@ public function failed_url_import_should_be_handled_gracefully(): void { // Setup mock response with error $this->mockHttpClient->addResponse( - 'https://example.com/not-found', - new HttpResponse( + url: 'https://example.com/not-found', + response: new HttpResponse( statusCode: 404, body: 'Not Found', headers: [], @@ -380,7 +380,7 @@ public function failed_url_import_should_be_handled_gracefully(): void import: - url: https://example.com/not-found type: url - + documents: - description: "Main Document" outputPath: "main.md" @@ -417,7 +417,7 @@ public function failed_url_import_should_be_handled_gracefully(): void public function url_import_with_multiple_urls_should_be_supported(): void { // Setup mock responses for multiple URLs - $jsonConfig1 = \json_encode([ + $jsonConfig1 = \json_encode(value: [ 'documents' => [ [ 'description' => 'First URL Document', @@ -434,7 +434,7 @@ public function url_import_with_multiple_urls_should_be_supported(): void ], ]); - $jsonConfig2 = \json_encode([ + $jsonConfig2 = \json_encode(value: [ 'documents' => [ [ 'description' => 'Second URL Document', @@ -452,8 +452,8 @@ public function url_import_with_multiple_urls_should_be_supported(): void ]); $this->mockHttpClient->addResponse( - 'https://example.com/config1.json', - new HttpResponse( + url: 'https://example.com/config1.json', + response: new HttpResponse( statusCode: 200, body: $jsonConfig1, headers: ['Content-Type' => 'application/json'], @@ -461,8 +461,8 @@ public function url_import_with_multiple_urls_should_be_supported(): void ); $this->mockHttpClient->addResponse( - 'https://example.com/config2.json', - new HttpResponse( + url: 'https://example.com/config2.json', + response: new HttpResponse( statusCode: 200, body: $jsonConfig2, headers: ['Content-Type' => 'application/json'], @@ -477,7 +477,7 @@ public function url_import_with_multiple_urls_should_be_supported(): void type: url - url: https://example.com/config2.json type: url - + documents: - description: "Main Document" outputPath: "main.md" @@ -553,8 +553,8 @@ public function url_import_with_filter_should_work(): void YAML; $this->mockHttpClient->addResponse( - 'https://example.com/prompts.yaml', - new HttpResponse( + url: 'https://example.com/prompts.yaml', + response: new HttpResponse( statusCode: 200, body: $yamlConfig, headers: ['Content-Type' => 'application/yaml'], @@ -571,7 +571,7 @@ public function url_import_with_filter_should_work(): void tags: include: ["coding"] exclude: ["advanced"] - + documents: - description: "Filtered Prompts Document" outputPath: "filtered-prompts.md" @@ -613,7 +613,7 @@ protected function setUp(): void $this->mockHttpClient = new MockHttpClient(); // Register mock HTTP client in the container - $this->getContainer()->bindSingleton(HttpClientInterface::class, $this->mockHttpClient); + $this->getContainer()->bindSingleton(alias: HttpClientInterface::class, resolver: $this->mockHttpClient); } protected function buildContext( @@ -624,7 +624,7 @@ protected function buildContext( string $command = 'generate', bool $asJson = true, ): CompilingResult { - return (new ContextBuilder($this->getConsole()))->build( + return (new ContextBuilder(console: $this->getConsole()))->build( workDir: $workDir, configPath: $configPath, inlineJson: $inlineJson, diff --git a/tests/src/Feature/Console/GenerateCommand/UrlSourceTest.php b/tests/src/Feature/Console/GenerateCommand/UrlSourceTest.php index 383a2f30..aa8e0509 100644 --- a/tests/src/Feature/Console/GenerateCommand/UrlSourceTest.php +++ b/tests/src/Feature/Console/GenerateCommand/UrlSourceTest.php @@ -28,8 +28,8 @@ public function basic_url_source_should_be_rendered(string $command): void { // Setup mock response $this->mockHttpClient->addResponse( - 'https://example.com/api', - new HttpResponse( + url: 'https://example.com/api', + response: new HttpResponse( statusCode: 200, body: '

Example API

This is example content

', headers: ['Content-Type' => 'text/html'], @@ -78,8 +78,8 @@ public function url_source_with_selector_should_extract_content(): void { // Setup mock response with content that has elements to select $this->mockHttpClient->addResponse( - 'https://example.com/docs', - new HttpResponse( + url: 'https://example.com/docs', + response: new HttpResponse( statusCode: 200, body: '
Header

Documentation

Selected content

', headers: ['Content-Type' => 'text/html'], @@ -113,8 +113,8 @@ public function url_source_with_headers_should_send_headers(): void { // Setup mock response $this->mockHttpClient->addResponse( - 'https://api.example.com/data', - new HttpResponse( + url: 'https://api.example.com/data', + response: new HttpResponse( statusCode: 200, body: '{"message": "Authentication successful", "data": {"name": "Test User", "email": "test@example.com"}}', headers: ['Content-Type' => 'application/json'], @@ -138,7 +138,7 @@ public function url_source_with_headers_should_send_headers(): void ); // Verify the headers were sent - $sentHeaders = $this->mockHttpClient->getRequestHeaders('https://api.example.com/data'); + $sentHeaders = $this->mockHttpClient->getRequestHeaders(url: 'https://api.example.com/data'); $this->assertArrayHasKey('Authorization', $sentHeaders); $this->assertEquals('Bearer test-token', $sentHeaders['Authorization']); $this->assertArrayHasKey('Accept', $sentHeaders); @@ -151,8 +151,8 @@ public function url_source_with_multiple_urls_should_fetch_all(): void { // Setup mock responses for multiple URLs $this->mockHttpClient->addResponse( - 'https://example.com/page1', - new HttpResponse( + url: 'https://example.com/page1', + response: new HttpResponse( statusCode: 200, body: '

Page 1

Content from page 1

', headers: ['Content-Type' => 'text/html'], @@ -160,8 +160,8 @@ public function url_source_with_multiple_urls_should_fetch_all(): void ); $this->mockHttpClient->addResponse( - 'https://example.com/page2', - new HttpResponse( + url: 'https://example.com/page2', + response: new HttpResponse( statusCode: 200, body: '

Page 2

Content from page 2

', headers: ['Content-Type' => 'text/html'], @@ -194,8 +194,8 @@ public function url_source_with_failed_request_should_show_error(): void { // Setup mock response with error $this->mockHttpClient->addResponse( - 'https://example.com/not-found', - new HttpResponse( + url: 'https://example.com/not-found', + response: new HttpResponse( statusCode: 404, body: 'Not Found', headers: [], @@ -224,8 +224,8 @@ public function url_source_with_variables_should_resolve_variables(): void { // Setup mock response $this->mockHttpClient->addResponse( - 'https://api.production.example.com/data', - new HttpResponse( + url: 'https://api.production.example.com/data', + response: new HttpResponse( statusCode: 200, body: '

Production API

This is production data

', headers: ['Content-Type' => 'text/html'], @@ -256,7 +256,7 @@ public function url_source_with_variables_should_resolve_variables(): void ); // Verify the headers were sent with resolved variables - $sentHeaders = $this->mockHttpClient->getRequestHeaders('https://api.production.example.com/data'); + $sentHeaders = $this->mockHttpClient->getRequestHeaders(url: 'https://api.production.example.com/data'); $this->assertArrayHasKey('Authorization', $sentHeaders); $this->assertEquals('Bearer prod-token', $sentHeaders['Authorization']); } @@ -271,7 +271,7 @@ protected function setUp(): void $this->mockHttpClient = new MockHttpClient(); // Register mock HTTP client in the container - $this->getContainer()->bindSingleton(HttpClientInterface::class, $this->mockHttpClient); + $this->getContainer()->bindSingleton(alias: HttpClientInterface::class, resolver: $this->mockHttpClient); } protected function buildContext( @@ -282,7 +282,7 @@ protected function buildContext( string $command = 'generate', bool $asJson = true, ): CompilingResult { - return (new ContextBuilder($this->getConsole()))->build( + return (new ContextBuilder(console: $this->getConsole()))->build( workDir: $workDir, configPath: $configPath, inlineJson: $inlineJson, diff --git a/tests/src/Feature/FeatureTestCases.php b/tests/src/Feature/FeatureTestCases.php index 5479fdeb..fb46f459 100644 --- a/tests/src/Feature/FeatureTestCases.php +++ b/tests/src/Feature/FeatureTestCases.php @@ -38,15 +38,15 @@ protected function tearDown(): void { parent::tearDown(); - if (\is_dir($this->getContextsDir())) { + if (\is_dir(filename: $this->getContextsDir())) { $files = new Files(); - $files->deleteDirectory($this->getContextsDir()); + $files->deleteDirectory(directory: $this->getContextsDir()); } } protected function getContextsDir(string $path = ''): string { - return (string) FSPath::create($this->getFixturesDir('Compiler/.context'))->join($path); + return (string) FSPath::create(path: $this->getFixturesDir('Compiler/.context'))->join($path); } abstract protected function getConfigPath(): string; @@ -58,8 +58,8 @@ abstract protected function assertConfigItems( private function compileDocuments(DocumentCompiler $compiler, ConfigurationProvider $configProvider): void { - $loader = $configProvider->fromPath($this->getConfigPath()); + $loader = $configProvider->fromPath(configPath: $this->getConfigPath()); - $this->assertConfigItems($compiler, new ConfigRegistryAccessor($loader->load())); + $this->assertConfigItems($compiler, new ConfigRegistryAccessor(registry: $loader->load())); } } diff --git a/tests/src/Feature/Research/Storage/FileStorage/DirectoryScannerTest.php b/tests/src/Feature/Research/Storage/FileStorage/DirectoryScannerTest.php index 142678e5..111875b6 100644 --- a/tests/src/Feature/Research/Storage/FileStorage/DirectoryScannerTest.php +++ b/tests/src/Feature/Research/Storage/FileStorage/DirectoryScannerTest.php @@ -20,12 +20,12 @@ final class DirectoryScannerTest extends TestCase public function it_scans_projects_correctly(): void { $projectsPath = $this->tempPath . '/projects'; - $projects = $this->scanner->scanResearches($projectsPath); + $projects = $this->scanner->scanResearches(path: $projectsPath); $this->assertCount(2, $projects); // Verify project paths - $projectNames = \array_map('basename', $projects); + $projectNames = \array_map(callback: 'basename', array: $projects); $this->assertContains('test_project_1', $projectNames); $this->assertContains('test_project_2', $projectNames); @@ -39,7 +39,7 @@ public function it_scans_projects_correctly(): void public function it_returns_empty_array_for_nonexistent_projects_path(): void { $nonexistentPath = $this->tempPath . '/nonexistent'; - $projects = $this->scanner->scanResearches($nonexistentPath); + $projects = $this->scanner->scanResearches(path: $nonexistentPath); $this->assertEmpty($projects); } @@ -49,16 +49,16 @@ public function it_ignores_directories_without_project_yaml(): void { // Create a directory without project.yaml $invalidProjectPath = $this->tempPath . '/projects/invalid_project'; - \mkdir($invalidProjectPath, 0755, true); - \file_put_contents($invalidProjectPath . '/readme.txt', 'Not a project'); + \mkdir(directory: $invalidProjectPath, permissions: 0755, recursive: true); + \file_put_contents(filename: $invalidProjectPath . '/readme.txt', data: 'Not a project'); $projectsPath = $this->tempPath . '/projects'; - $projects = $this->scanner->scanResearches($projectsPath); + $projects = $this->scanner->scanResearches(path: $projectsPath); // Should still only find the 2 valid projects $this->assertCount(2, $projects); - $projectNames = \array_map('basename', $projects); + $projectNames = \array_map(callback: 'basename', array: $projects); $this->assertNotContains('invalid_project', $projectNames); } @@ -67,12 +67,12 @@ public function it_scans_entries_in_project(): void { $projectPath = $this->tempPath . '/projects/test_project_1'; - $entries = $this->scanner->scanEntries($projectPath); + $entries = $this->scanner->scanEntries(path: $projectPath); $this->assertCount(3, $entries); // Verify entry file paths - $entryFiles = \array_map('basename', $entries); + $entryFiles = \array_map(callback: 'basename', array: $entries); $this->assertContains('sample_story.md', $entryFiles); $this->assertContains('api_design.md', $entryFiles); } @@ -82,7 +82,7 @@ public function it_scans_all_markdown_files_when_no_entry_dirs_specified(): void { $projectPath = $this->tempPath . '/projects/test_project_1'; - $entries = $this->scanner->scanEntries($projectPath); + $entries = $this->scanner->scanEntries(path: $projectPath); $this->assertCount(3, $entries); @@ -95,7 +95,7 @@ public function it_scans_all_markdown_files_when_no_entry_dirs_specified(): void public function it_returns_empty_array_for_nonexistent_project_path(): void { $nonexistentPath = $this->tempPath . '/projects/nonexistent_project'; - $entries = $this->scanner->scanEntries($nonexistentPath); + $entries = $this->scanner->scanEntries(path: $nonexistentPath); $this->assertEmpty($entries); } @@ -104,7 +104,7 @@ public function it_returns_empty_array_for_nonexistent_project_path(): void public function it_handles_project_with_no_entries(): void { $projectPath = $this->tempPath . '/projects/test_project_2'; - $entries = $this->scanner->scanEntries($projectPath); + $entries = $this->scanner->scanEntries(path: $projectPath); $this->assertEmpty($entries); } @@ -113,9 +113,9 @@ public function it_handles_project_with_no_entries(): void public function it_gets_entry_directories(): void { $projectPath = $this->tempPath . '/projects/test_project_1'; - $directories = $this->scanner->getEntryDirectories($projectPath); + $directories = $this->scanner->getEntryDirectories(path: $projectPath); - $this->assertGreaterThan(0, \count($directories)); + $this->assertGreaterThan(0, \count(value: $directories)); $this->assertContains('features', $directories); $this->assertContains('docs', $directories); } @@ -129,12 +129,12 @@ public function it_excludes_special_directories(): void foreach ($specialDirs as $specialDir) { $dirPath = $projectPath . '/' . $specialDir; - if (!\is_dir($dirPath)) { - \mkdir($dirPath, 0755, true); + if (!\is_dir(filename: $dirPath)) { + \mkdir(directory: $dirPath, permissions: 0755, recursive: true); } } - $directories = $this->scanner->getEntryDirectories($projectPath); + $directories = $this->scanner->getEntryDirectories(path: $projectPath); foreach ($specialDirs as $specialDir) { $this->assertNotContains($specialDir, $directories); @@ -145,7 +145,7 @@ public function it_excludes_special_directories(): void public function it_returns_empty_array_for_nonexistent_directory(): void { $nonexistentPath = $this->tempPath . '/nonexistent_directory'; - $directories = $this->scanner->getEntryDirectories($nonexistentPath); + $directories = $this->scanner->getEntryDirectories(path: $nonexistentPath); $this->assertEmpty($directories); } @@ -156,7 +156,7 @@ public function it_handles_deeply_nested_entry_files(): void // Create nested entry structure $projectPath = $this->tempPath . '/projects/test_project_1'; $nestedPath = $projectPath . '/features/user_story/nested'; - \mkdir($nestedPath, 0755, true); + \mkdir(directory: $nestedPath, permissions: 0755, recursive: true); $nestedEntryContent = <<<'MARKDOWN' --- @@ -172,16 +172,16 @@ public function it_handles_deeply_nested_entry_files(): void This is a nested entry for testing. MARKDOWN; - \file_put_contents($nestedPath . '/nested_entry.md', $nestedEntryContent); + \file_put_contents(filename: $nestedPath . '/nested_entry.md', data: $nestedEntryContent); - $entries = $this->scanner->scanEntries($projectPath); + $entries = $this->scanner->scanEntries(path: $projectPath); // Should include the nested entry $this->assertCount(4, $entries); // Original 2 + new nested one $nestedEntryFound = false; foreach ($entries as $entryPath) { - if (\str_contains((string) $entryPath, 'nested_entry.md')) { + if (\str_contains(haystack: (string) $entryPath, needle: 'nested_entry.md')) { $nestedEntryFound = true; break; } @@ -195,11 +195,11 @@ public function it_only_finds_markdown_files(): void { // Create non-markdown files $projectPath = $this->tempPath . '/projects/test_project_1'; - \file_put_contents($projectPath . '/features/readme.txt', 'Not an entry'); - \file_put_contents($projectPath . '/docs/config.json', '{"not": "an entry"}'); - \file_put_contents($projectPath . '/notes.html', '

Not an entry

'); + \file_put_contents(filename: $projectPath . '/features/readme.txt', data: 'Not an entry'); + \file_put_contents(filename: $projectPath . '/docs/config.json', data: '{"not": "an entry"}'); + \file_put_contents(filename: $projectPath . '/notes.html', data: '

Not an entry

'); - $entries = $this->scanner->scanEntries($projectPath); + $entries = $this->scanner->scanEntries(path: $projectPath); // Should only find .md files foreach ($entries as $entryPath) { @@ -215,12 +215,12 @@ public function it_handles_empty_project_directory(): void { // Create completely empty project directory $emptyProjectPath = $this->tempPath . '/projects/empty_project'; - \mkdir($emptyProjectPath, 0755, true); + \mkdir(directory: $emptyProjectPath, permissions: 0755, recursive: true); - $entries = $this->scanner->scanEntries($emptyProjectPath); + $entries = $this->scanner->scanEntries(path: $emptyProjectPath); $this->assertEmpty($entries); - $directories = $this->scanner->getEntryDirectories($emptyProjectPath); + $directories = $this->scanner->getEntryDirectories(path: $emptyProjectPath); $this->assertEmpty($directories); } @@ -228,7 +228,7 @@ protected function setUp(): void { parent::setUp(); - $this->testDataPath = \dirname(__DIR__, 5) . '/fixtures/Research/FileStorage'; + $this->testDataPath = \dirname(path: __DIR__, levels: 5) . '/fixtures/Research/FileStorage'; $this->tempPath = \sys_get_temp_dir() . '/scanner_test_' . \uniqid(); // Copy fixture data to temp directory @@ -242,13 +242,13 @@ public function report(\Throwable $exception): void } }; - $this->scanner = new DirectoryScanner($files, $reporter); + $this->scanner = new DirectoryScanner(files: $files, reporter: $reporter); } protected function tearDown(): void { // Clean up temp directory - if (\is_dir($this->tempPath)) { + if (\is_dir(filename: $this->tempPath)) { $this->removeDirectory($this->tempPath); } @@ -257,8 +257,8 @@ protected function tearDown(): void private function copyFixturesToTemp(): void { - if (!\is_dir($this->tempPath)) { - \mkdir($this->tempPath, 0755, true); + if (!\is_dir(filename: $this->tempPath)) { + \mkdir(directory: $this->tempPath, permissions: 0755, recursive: true); } $this->copyDirectory($this->testDataPath, $this->tempPath); @@ -266,47 +266,47 @@ private function copyFixturesToTemp(): void private function copyDirectory(string $source, string $destination): void { - if (!\is_dir($destination)) { - \mkdir($destination, 0755, true); + if (!\is_dir(filename: $destination)) { + \mkdir(directory: $destination, permissions: 0755, recursive: true); } $iterator = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS), - \RecursiveIteratorIterator::SELF_FIRST, + iterator: new \RecursiveDirectoryIterator(directory: $source, flags: \RecursiveDirectoryIterator::SKIP_DOTS), + mode: \RecursiveIteratorIterator::SELF_FIRST, ); foreach ($iterator as $item) { $destPath = $destination . DIRECTORY_SEPARATOR . $iterator->getSubPathName(); if ($item->isDir()) { - if (!\is_dir($destPath)) { - \mkdir($destPath, 0755, true); + if (!\is_dir(filename: $destPath)) { + \mkdir(directory: $destPath, permissions: 0755, recursive: true); } } else { - \copy($item->getRealPath(), $destPath); + \copy(from: $item->getRealPath(), to: $destPath); } } } private function removeDirectory(string $directory): void { - if (!\is_dir($directory)) { + if (!\is_dir(filename: $directory)) { return; } $iterator = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator($directory, \RecursiveDirectoryIterator::SKIP_DOTS), - \RecursiveIteratorIterator::CHILD_FIRST, + iterator: new \RecursiveDirectoryIterator(directory: $directory, flags: \RecursiveDirectoryIterator::SKIP_DOTS), + mode: \RecursiveIteratorIterator::CHILD_FIRST, ); foreach ($iterator as $item) { if ($item->isDir()) { - \rmdir($item->getRealPath()); + \rmdir(directory: $item->getRealPath()); } else { - \unlink($item->getRealPath()); + \unlink(filename: $item->getRealPath()); } } - \rmdir($directory); + \rmdir(directory: $directory); } } diff --git a/tests/src/Feature/Research/Storage/FileStorage/FrontmatterParserTest.php b/tests/src/Feature/Research/Storage/FileStorage/FrontmatterParserTest.php index 302ec235..617bee0b 100644 --- a/tests/src/Feature/Research/Storage/FileStorage/FrontmatterParserTest.php +++ b/tests/src/Feature/Research/Storage/FileStorage/FrontmatterParserTest.php @@ -33,7 +33,7 @@ public function it_parses_content_with_frontmatter(): void Some more content here. MARKDOWN; - $result = $this->parser->parse($content); + $result = $this->parser->parse(content: $content); $this->assertArrayHasKey('frontmatter', $result); $this->assertArrayHasKey('content', $result); @@ -62,7 +62,7 @@ public function it_parses_content_without_frontmatter(): void More content here. MARKDOWN; - $result = $this->parser->parse($content); + $result = $this->parser->parse(content: $content); $this->assertArrayHasKey('frontmatter', $result); $this->assertArrayHasKey('content', $result); @@ -83,7 +83,7 @@ public function it_handles_empty_frontmatter(): void This has empty frontmatter. MARKDOWN; - $result = $this->parser->parse($content); + $result = $this->parser->parse(content: $content); $this->assertEmpty($result['frontmatter']); $this->assertEquals("# Content Only\n\nThis has empty frontmatter.", $result['content']); @@ -115,7 +115,7 @@ public function it_handles_complex_yaml_frontmatter(): void This entry has complex YAML frontmatter. MARKDOWN; - $result = $this->parser->parse($content); + $result = $this->parser->parse(content: $content); $frontmatter = $result['frontmatter']; $this->assertEquals('entry_123', $frontmatter['entry_info']['id']); @@ -139,7 +139,7 @@ public function it_combines_frontmatter_and_content(): void $content = "# Combined Entry\n\nThis content was combined with frontmatter."; - $result = $this->parser->combine($frontmatter, $content); + $result = $this->parser->combine(frontmatter: $frontmatter, content: $content); $expectedOutput = <<<'MARKDOWN' --- @@ -164,7 +164,7 @@ public function it_combines_empty_frontmatter_with_content(): void $frontmatter = []; $content = "# Content Only\n\nJust content, no frontmatter."; - $result = $this->parser->combine($frontmatter, $content); + $result = $this->parser->combine(frontmatter: $frontmatter, content: $content); $this->assertEquals($content, $result); } @@ -184,7 +184,7 @@ public function it_extracts_frontmatter_only(): void This content is not extracted. MARKDOWN; - $frontmatter = $this->parser->extractFrontmatter($content); + $frontmatter = $this->parser->extractFrontmatter(content: $content); $this->assertEquals('Extract Test', $frontmatter['title']); $this->assertEquals('published', $frontmatter['status']); @@ -207,7 +207,7 @@ public function it_throws_exception_for_invalid_yaml(): void $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('Failed to parse YAML frontmatter'); - $this->parser->parse($content); + $this->parser->parse(content: $content); } #[Test] @@ -225,7 +225,7 @@ public function it_handles_frontmatter_with_special_characters(): void Content with special characters. MARKDOWN; - $result = $this->parser->parse($content); + $result = $this->parser->parse(content: $content); $frontmatter = $result['frontmatter']; $this->assertEquals("Entry with 'quotes' and \"double quotes\"", $frontmatter['title']); @@ -254,7 +254,7 @@ public function it_handles_multiline_yaml_values(): void Test content. MARKDOWN; - $result = $this->parser->parse($content); + $result = $this->parser->parse(content: $content); $frontmatter = $result['frontmatter']; $this->assertEquals('Multiline Test', $frontmatter['title']); @@ -291,7 +291,7 @@ function test() { > with multiple lines. MARKDOWN; - $result = $this->parser->parse($content); + $result = $this->parser->parse(content: $content); $expectedContent = <<<'CONTENT' # Main Title diff --git a/tests/src/Feature/Source/File/AbstractFileSourceTestCase.php b/tests/src/Feature/Source/File/AbstractFileSourceTestCase.php index 0d7df523..d53209fc 100644 --- a/tests/src/Feature/Source/File/AbstractFileSourceTestCase.php +++ b/tests/src/Feature/Source/File/AbstractFileSourceTestCase.php @@ -46,7 +46,7 @@ protected function getFileSourceFromConfig(ConfigRegistryAccessor $config): File */ protected function getSourceType(SourceInterface $source): string { - return \json_decode(\json_encode($source), true)['type'] ?? ''; + return \json_decode(json: \json_encode(value: $source), associative: true)['type'] ?? ''; } /** @@ -58,19 +58,19 @@ protected function createTestFileStructure(): string // Create a basic structure $rootFile = $tempDir . '/root_file.txt'; - \file_put_contents($rootFile, 'Root file content'); + \file_put_contents(filename: $rootFile, data: 'Root file content'); $subDir = $tempDir . '/subdir'; - \mkdir($subDir, 0777, true); + \mkdir(directory: $subDir, recursive: true); $nestedFile = $subDir . '/nested_file.txt'; - \file_put_contents($nestedFile, 'Nested file content'); + \file_put_contents(filename: $nestedFile, data: 'Nested file content'); $deepDir = $subDir . '/deep'; - \mkdir($deepDir, 0777, true); + \mkdir(directory: $deepDir, recursive: true); $deepFile = $deepDir . '/deep_file.txt'; - \file_put_contents($deepFile, 'Deep nested file content'); + \file_put_contents(filename: $deepFile, data: 'Deep nested file content'); return $tempDir; } diff --git a/tests/src/Feature/Source/File/FileSourceFilterTest.php b/tests/src/Feature/Source/File/FileSourceFilterTest.php index 3103e5bd..5a551164 100644 --- a/tests/src/Feature/Source/File/FileSourceFilterTest.php +++ b/tests/src/Feature/Source/File/FileSourceFilterTest.php @@ -34,7 +34,7 @@ protected function assertConfigItems(DocumentCompiler $compiler, ConfigRegistryA $this->assertEquals('nested file', $source->contains); // Compile and verify content filtering worked - $compiledDocument = $compiler->compile($document); + $compiledDocument = $compiler->compile(document: $document); $content = (string) $compiledDocument->content; // Should include nested file but not the root test_file.txt diff --git a/tests/src/Feature/Source/File/FileSourceSerializationTest.php b/tests/src/Feature/Source/File/FileSourceSerializationTest.php index 00da95f1..b882624d 100644 --- a/tests/src/Feature/Source/File/FileSourceSerializationTest.php +++ b/tests/src/Feature/Source/File/FileSourceSerializationTest.php @@ -27,10 +27,10 @@ protected function assertConfigItems(DocumentCompiler $compiler, ConfigRegistryA $source = $this->getFileSourceFromConfig($config); // Test JSON serialization - $serialized = \json_encode($source); + $serialized = \json_encode(value: $source); $this->assertNotFalse($serialized, 'JSON serialization failed'); - $decoded = \json_decode($serialized, true); + $decoded = \json_decode(json: $serialized, associative: true); $this->assertIsArray($decoded); // Check required fields @@ -47,10 +47,10 @@ protected function assertConfigItems(DocumentCompiler $compiler, ConfigRegistryA description: 'Minimal source', ); - $minimalSerialized = \json_encode($minimalSource); + $minimalSerialized = \json_encode(value: $minimalSource); $this->assertNotFalse($minimalSerialized, 'Minimal source JSON serialization failed'); - $minimalDecoded = \json_decode($minimalSerialized, true); + $minimalDecoded = \json_decode(json: $minimalSerialized, associative: true); $this->assertIsArray($minimalDecoded); // Check that optional fields are not included when empty @@ -80,10 +80,10 @@ protected function assertConfigItems(DocumentCompiler $compiler, ConfigRegistryA maxFiles: 10, ); - $fullSerialized = \json_encode($fullSource); + $fullSerialized = \json_encode(value: $fullSource); $this->assertNotFalse($fullSerialized, 'Full source JSON serialization failed'); - $fullDecoded = \json_decode($fullSerialized, true); + $fullDecoded = \json_decode(json: $fullSerialized, associative: true); $this->assertIsArray($fullDecoded); // Check that all options are serialized diff --git a/tests/src/Feature/Source/File/FileSourceTest.php b/tests/src/Feature/Source/File/FileSourceTest.php index bb0bbc89..5d4e27a4 100644 --- a/tests/src/Feature/Source/File/FileSourceTest.php +++ b/tests/src/Feature/Source/File/FileSourceTest.php @@ -37,7 +37,7 @@ protected function assertConfigItems(DocumentCompiler $compiler, ConfigRegistryA // Verify document properties $document = $documents[0]; $this->assertEquals('File Source Test Document', $document->description); - $compiledDocument = $compiler->compile($document); + $compiledDocument = $compiler->compile(document: $document); $content = (string) $compiledDocument->content; // Check for expected content in the output diff --git a/tests/src/Feature/Source/File/FileSourceTreeViewTest.php b/tests/src/Feature/Source/File/FileSourceTreeViewTest.php index fd309c97..299e8dc9 100644 --- a/tests/src/Feature/Source/File/FileSourceTreeViewTest.php +++ b/tests/src/Feature/Source/File/FileSourceTreeViewTest.php @@ -38,7 +38,7 @@ protected function assertConfigItems(DocumentCompiler $compiler, ConfigRegistryA $this->assertEquals(2, $treeView->maxDepth); // Compile and verify tree view output - $compiledDocument = $compiler->compile($document); + $compiledDocument = $compiler->compile(document: $document); $content = (string) $compiledDocument->content; // Check that the tree view formatting shows the configured information diff --git a/tests/src/TestCase.php b/tests/src/TestCase.php index d25bab59..b65e0456 100644 --- a/tests/src/TestCase.php +++ b/tests/src/TestCase.php @@ -35,8 +35,8 @@ protected function tearDown(): void // Clean up temp files foreach ($this->tempFiles as $file) { - if (\file_exists($file)) { - \unlink($file); + if (\file_exists(filename: $file)) { + \unlink(filename: $file); } } @@ -79,8 +79,8 @@ protected function getFixturesDir(string $subdirectory = ''): string */ protected function createTempFile(string $content, string $extension = '.txt'): string { - $tempFile = \tempnam(\sys_get_temp_dir(), 'test_') . $extension; - \file_put_contents($tempFile, $content); + $tempFile = \tempnam(directory: \sys_get_temp_dir(), prefix: 'test_') . $extension; + \file_put_contents(filename: $tempFile, data: $content); // Register for cleanup $this->registerTempFile($tempFile); @@ -104,7 +104,7 @@ protected function registerTempFile(string $filePath): void protected function createTempDir(): string { $tempDir = \sys_get_temp_dir() . '/test_' . \uniqid(); - \mkdir($tempDir, 0777, true); + \mkdir(directory: $tempDir, recursive: true); // Register for cleanup $this->registerTempDir($tempDir); @@ -125,11 +125,11 @@ protected function registerTempDir(string $dirPath): void */ private function removeDirectory(string $dir): void { - if (!\is_dir($dir)) { + if (!\is_dir(filename: $dir)) { return; } - $items = \scandir($dir); + $items = \scandir(directory: $dir); foreach ($items as $item) { if ($item === '.' || $item === '..') { @@ -138,13 +138,13 @@ private function removeDirectory(string $dir): void $path = $dir . '/' . $item; - if (\is_dir($path)) { + if (\is_dir(filename: $path)) { $this->removeDirectory($path); } else { - \unlink($path); + \unlink(filename: $path); } } - \rmdir($dir); + \rmdir(directory: $dir); } } diff --git a/tests/src/Unit/Application/FSPathLinuxTest.php b/tests/src/Unit/Application/FSPathLinuxTest.php index 4eb46b75..de1de711 100644 --- a/tests/src/Unit/Application/FSPathLinuxTest.php +++ b/tests/src/Unit/Application/FSPathLinuxTest.php @@ -47,7 +47,7 @@ public static function provideRelativePathTests(): \Generator #[Test] public function it_should_create_path_from_string(): void { - $path = FSPath::create('/home/user/test'); + $path = FSPath::create(path: '/home/user/test'); $this->assertSame('/home/user/test', $path->toString()); } @@ -66,7 +66,7 @@ public function it_should_create_path_from_cwd(): void #[Test] public function it_should_join_paths_correctly(): void { - $base = FSPath::create('/home/user'); + $base = FSPath::create(path: '/home/user'); $joined = $base->join('../test'); $this->assertSame('/home/test', $joined->toString()); @@ -75,9 +75,9 @@ public function it_should_join_paths_correctly(): void #[Test] public function it_should_handle_name_operations(): void { - $path = FSPath::create('/home/user/document.txt'); + $path = FSPath::create(path: '/home/user/document.txt'); - $newPath = $path->withName('new.txt'); + $newPath = $path->withName(name: 'new.txt'); $this->assertSame('/home/user/new.txt', $newPath->toString()); $stem = $path->stem(); @@ -93,23 +93,23 @@ public function it_should_handle_name_operations(): void #[Test] public function it_should_handle_extension_operations(): void { - $path = FSPath::create('/home/user/document.txt'); + $path = FSPath::create(path: '/home/user/document.txt'); - $newPath = $path->withExt('md'); + $newPath = $path->withExt(suffix: 'md'); $this->assertSame('/home/user/document.md', $newPath->toString()); - $newPath = $path->withExt('.md'); + $newPath = $path->withExt(suffix: '.md'); $this->assertSame('/home/user/document.md', $newPath->toString()); // Bug test - $newPath = $path->withStem('report'); + $newPath = $path->withStem(stem: 'report'); $this->assertSame('/home/user/report.txt', $newPath->toString()); } #[Test] public function it_should_get_parent_directory(): void { - $path = FSPath::create('/home/user/document.txt'); + $path = FSPath::create(path: '/home/user/document.txt'); $parent = $path->parent(); $this->assertSame('/home/user', $parent->toString()); @@ -121,25 +121,25 @@ public function it_should_get_parent_directory(): void #[Test] public function it_should_handle_root_paths(): void { - $root = FSPath::create('/'); + $root = FSPath::create(path: '/'); // Root parent should be itself $this->assertSame('/', $root->parent()->toString()); // These operations should not change a root path - $this->assertSame('/', $root->withName('test')->toString()); - $this->assertSame('/', $root->withExt('txt')->toString()); - $this->assertSame('/', $root->withStem('test')->toString()); + $this->assertSame('/', $root->withName(name: 'test')->toString()); + $this->assertSame('/', $root->withExt(suffix: 'txt')->toString()); + $this->assertSame('/', $root->withStem(stem: 'test')->toString()); } #[Test] public function it_should_check_path_types(): void { - $absolutePath = FSPath::create('/home/user'); + $absolutePath = FSPath::create(path: '/home/user'); $this->assertTrue($absolutePath->isAbsolute()); $this->assertFalse($absolutePath->isRelative()); - $relativePath = FSPath::create('home/user'); + $relativePath = FSPath::create(path: 'home/user'); $this->assertFalse($relativePath->isAbsolute()); $this->assertTrue($relativePath->isRelative()); } @@ -148,10 +148,10 @@ public function it_should_check_path_types(): void #[DataProvider('provideRelativePathTests')] public function it_should_handle_relative_paths(string $from, string $to, string $expected): void { - $fromPath = FSPath::create($from); - $toPath = FSPath::create($to); + $fromPath = FSPath::create(path: $from); + $toPath = FSPath::create(path: $to); - $relativePath = $toPath->relativeTo($fromPath); + $relativePath = $toPath->relativeTo(other: $fromPath); $this->assertSame($expected, $relativePath->toString()); } @@ -159,22 +159,22 @@ public function it_should_handle_relative_paths(string $from, string $to, string public function it_should_normalize_paths(): void { // Mixed separators (should convert to Linux format) - $path = FSPath::create('/home\\user/documents'); + $path = FSPath::create(path: '/home\\user/documents'); $this->assertSame('/home/user/documents', $path->toString()); // Double separators - $path = FSPath::create('/home//user///documents'); + $path = FSPath::create(path: '/home//user///documents'); $this->assertSame('/home/user/documents', $path->toString()); // Dot segments - $path = FSPath::create('/home/./user/../admin'); + $path = FSPath::create(path: '/home/./user/../admin'); $this->assertSame('/home/admin', $path->toString()); } #[Test] public function it_should_split_path_into_parts(): void { - $path = FSPath::create('/home/user/documents/file.txt'); + $path = FSPath::create(path: '/home/user/documents/file.txt'); $parts = $path->parts(); $this->assertSame(['home', 'user', 'documents', 'file.txt'], $parts); @@ -183,7 +183,7 @@ public function it_should_split_path_into_parts(): void #[Test] public function it_should_handle_stringable_interface(): void { - $path = FSPath::create('/home/user'); + $path = FSPath::create(path: '/home/user'); $this->assertSame('/home/user', (string) $path); $this->assertSame($path->toString(), (string) $path); @@ -192,7 +192,7 @@ public function it_should_handle_stringable_interface(): void #[Test] public function it_should_handle_empty_paths(): void { - $path = FSPath::create(''); + $path = FSPath::create(); $this->assertSame('.', $path->toString()); $this->assertFalse($path->isAbsolute()); @@ -205,7 +205,7 @@ public function it_should_make_paths_absolute(): void // Mock cwd for predictable test $mockCwd = \getcwd(); - $relative = FSPath::create('html/css'); + $relative = FSPath::create(path: 'html/css'); $absolute = $relative->absolute(); $this->assertSame($mockCwd . '/html/css', $absolute->toString()); @@ -217,7 +217,7 @@ public function it_should_check_file_operations(): void // These tests would typically use a virtual filesystem library like vfsStream // or mock the file functions, but for simplicity we're just testing the method exists - $path = FSPath::create('/tmp/test-file.txt'); + $path = FSPath::create(path: '/tmp/test-file.txt'); // We can't guarantee these will pass on all systems, so we're just testing the methods exist $this->assertIsCallable($path->exists(...)); @@ -228,7 +228,7 @@ public function it_should_check_file_operations(): void #[Test] public function it_should_handle_path_with_no_extension(): void { - $path = FSPath::create('/home/user/document'); + $path = FSPath::create(path: '/home/user/document'); $extension = $path->extension(); $this->assertSame('', $extension); @@ -236,7 +236,7 @@ public function it_should_handle_path_with_no_extension(): void $stem = $path->stem(); $this->assertSame('document', $stem); - $newPath = $path->withExt('txt'); + $newPath = $path->withExt(suffix: 'txt'); $this->assertSame('/home/user/document.txt', $newPath->toString()); } @@ -244,15 +244,15 @@ public function it_should_handle_path_with_no_extension(): void public function it_should_properly_add_extension_prefix_when_changing_stem(): void { // Test specifically for the bug where withStem doesn't add the period before extension - $path = FSPath::create('/home/user/document.txt'); + $path = FSPath::create(path: '/home/user/document.txt'); - $newPath = $path->withStem('report'); + $newPath = $path->withStem(stem: 'report'); $this->assertSame('/home/user/report.txt', $newPath->toString()); // Also test with no extension - $path = FSPath::create('/home/user/document'); + $path = FSPath::create(path: '/home/user/document'); - $newPath = $path->withStem('report'); + $newPath = $path->withStem(stem: 'report'); $this->assertSame('/home/user/report', $newPath->toString()); } @@ -260,7 +260,7 @@ protected function setUp(): void { // Override directory separator for testing on non-Linux systems if (DIRECTORY_SEPARATOR !== self::LINUX_DIRECTORY_SEPARATOR) { - FSPath::setDirectorySeparator(self::LINUX_DIRECTORY_SEPARATOR); + FSPath::setDirectorySeparator(separator: self::LINUX_DIRECTORY_SEPARATOR); $this->isSeparatorOverridden = true; } } @@ -269,7 +269,7 @@ protected function tearDown(): void { // Reset directory separator if it was overridden if ($this->isSeparatorOverridden) { - FSPath::setDirectorySeparator(null); + FSPath::setDirectorySeparator(); } } } diff --git a/tests/src/Unit/Application/FSPathMixedSlashTest.php b/tests/src/Unit/Application/FSPathMixedSlashTest.php index 57a78350..30885f69 100644 --- a/tests/src/Unit/Application/FSPathMixedSlashTest.php +++ b/tests/src/Unit/Application/FSPathMixedSlashTest.php @@ -48,13 +48,13 @@ public static function provideRelativePathsWithMixedSlashes(): \Generator public function it_should_normalize_windows_paths_with_forward_slashes(): void { // Test with Windows separator - FSPath::setDirectorySeparator('\\'); - $path = FSPath::create('C:/Users/test/documents'); + FSPath::setDirectorySeparator(separator: '\\'); + $path = FSPath::create(path: 'C:/Users/test/documents'); $this->assertSame('C:\\Users\\test\\documents', $path->toString()); // Test with Unix separator - FSPath::setDirectorySeparator('/'); - $path = FSPath::create('C:/Users/test/documents'); + FSPath::setDirectorySeparator(separator: '/'); + $path = FSPath::create(path: 'C:/Users/test/documents'); $this->assertSame('C:/Users/test/documents', $path->toString()); } @@ -62,14 +62,14 @@ public function it_should_normalize_windows_paths_with_forward_slashes(): void public function it_should_join_mixed_slash_paths(): void { // Test with Windows separator - FSPath::setDirectorySeparator('\\'); - $base = FSPath::create('C:/Users'); + FSPath::setDirectorySeparator(separator: '\\'); + $base = FSPath::create(path: 'C:/Users'); $joined = $base->join('test\\documents', 'files/data'); $this->assertSame('C:\\Users\\test\\documents\\files\\data', $joined->toString()); // Test with Unix separator - FSPath::setDirectorySeparator('/'); - $base = FSPath::create('C:/Users'); + FSPath::setDirectorySeparator(separator: '/'); + $base = FSPath::create(path: 'C:/Users'); $joined = $base->join('test\\documents', 'files/data'); $this->assertSame('C:/Users/test/documents/files/data', $joined->toString()); } @@ -78,16 +78,16 @@ public function it_should_join_mixed_slash_paths(): void public function it_should_handle_typical_git_style_paths(): void { // Test with Windows separator - FSPath::setDirectorySeparator('\\'); - $path = FSPath::create('D:/git/project/.git/config'); + FSPath::setDirectorySeparator(separator: '\\'); + $path = FSPath::create(path: 'D:/git/project/.git/config'); $this->assertSame('D:\\git\\project\\.git\\config', $path->toString()); $parent = $path->parent(); $this->assertSame('D:\\git\\project\\.git', $parent->toString()); // Test with Unix separator - FSPath::setDirectorySeparator('/'); - $path = FSPath::create('D:/git/project/.git/config'); + FSPath::setDirectorySeparator(separator: '/'); + $path = FSPath::create(path: 'D:/git/project/.git/config'); $this->assertSame('D:/git/project/.git/config', $path->toString()); $parent = $path->parent(); @@ -98,8 +98,8 @@ public function it_should_handle_typical_git_style_paths(): void public function it_should_detect_absolute_paths_with_forward_slashes(): void { // Windows absolute path detection with forward slashes - FSPath::setDirectorySeparator('\\'); - $path = FSPath::create('C:/Users/test'); + FSPath::setDirectorySeparator(separator: '\\'); + $path = FSPath::create(path: 'C:/Users/test'); $this->assertTrue($path->isAbsolute()); $this->assertFalse($path->isRelative()); } @@ -108,20 +108,20 @@ public function it_should_detect_absolute_paths_with_forward_slashes(): void public function it_should_handle_file_operations_with_mixed_slashes(): void { // Test with Windows separator - FSPath::setDirectorySeparator('\\'); - $path = FSPath::create('C:/Users/test/document.txt'); + FSPath::setDirectorySeparator(separator: '\\'); + $path = FSPath::create(path: 'C:/Users/test/document.txt'); $extension = $path->extension(); $this->assertSame('txt', $extension); - $newPath = $path->withStem('report'); + $newPath = $path->withStem(stem: 'report'); $this->assertSame('C:\\Users\\test\\report.txt', $newPath->toString()); // Test with Unix separator - FSPath::setDirectorySeparator('/'); - $path = FSPath::create('C:/Users/test/document.txt'); + FSPath::setDirectorySeparator(separator: '/'); + $path = FSPath::create(path: 'C:/Users/test/document.txt'); - $newPath = $path->withStem('report'); + $newPath = $path->withStem(stem: 'report'); $this->assertSame('C:/Users/test/report.txt', $newPath->toString()); } @@ -129,14 +129,14 @@ public function it_should_handle_file_operations_with_mixed_slashes(): void public function it_should_handle_mixing_slashes_in_path_segments(): void { // Test with Windows separator - FSPath::setDirectorySeparator('\\'); - $path = FSPath::create('root'); + FSPath::setDirectorySeparator(separator: '\\'); + $path = FSPath::create(path: 'root'); $mixed = $path->join('folder1/sub1', 'folder2\\sub2'); $this->assertSame('root\\folder1\\sub1\\folder2\\sub2', $mixed->toString()); // Test with Unix separator - FSPath::setDirectorySeparator('/'); - $path = FSPath::create('root'); + FSPath::setDirectorySeparator(separator: '/'); + $path = FSPath::create(path: 'root'); $mixed = $path->join('folder1/sub1', 'folder2\\sub2'); $this->assertSame('root/folder1/sub1/folder2/sub2', $mixed->toString()); } @@ -145,25 +145,25 @@ public function it_should_handle_mixing_slashes_in_path_segments(): void public function it_should_handle_configuration_file_paths(): void { // Test with Windows separator - specific example from the request - FSPath::setDirectorySeparator('\\'); - $configPath = FSPath::create('D:/git/context.yaml'); + FSPath::setDirectorySeparator(separator: '\\'); + $configPath = FSPath::create(path: 'D:/git/context.yaml'); $this->assertSame('D:\\git\\context.yaml', $configPath->toString()); $parentDir = $configPath->parent(); $this->assertSame('D:\\git', $parentDir->toString()); - $newName = $configPath->withName('context.json'); + $newName = $configPath->withName(name: 'context.json'); $this->assertSame('D:\\git\\context.json', $newName->toString()); // Test with Unix separator - FSPath::setDirectorySeparator('/'); - $configPath = FSPath::create('D:/git/context.yaml'); + FSPath::setDirectorySeparator(separator: '/'); + $configPath = FSPath::create(path: 'D:/git/context.yaml'); $this->assertSame('D:/git/context.yaml', $configPath->toString()); $parentDir = $configPath->parent(); $this->assertSame('D:/git', $parentDir->toString()); - $newName = $configPath->withName('context.json'); + $newName = $configPath->withName(name: 'context.json'); $this->assertSame('D:/git/context.json', $newName->toString()); } @@ -176,17 +176,17 @@ public function it_should_handle_relative_paths_with_mixed_slashes( string $expectedUnix, ): void { // Test with Windows separator - FSPath::setDirectorySeparator('\\'); - $fromPath = FSPath::create($from); - $toPath = FSPath::create($to); - $relativePath = $toPath->relativeTo($fromPath); + FSPath::setDirectorySeparator(separator: '\\'); + $fromPath = FSPath::create(path: $from); + $toPath = FSPath::create(path: $to); + $relativePath = $toPath->relativeTo(other: $fromPath); $this->assertSame($expectedWindows, $relativePath->toString()); // Test with Unix separator - FSPath::setDirectorySeparator('/'); - $fromPath = FSPath::create($from); - $toPath = FSPath::create($to); - $relativePath = $toPath->relativeTo($fromPath); + FSPath::setDirectorySeparator(separator: '/'); + $fromPath = FSPath::create(path: $from); + $toPath = FSPath::create(path: $to); + $relativePath = $toPath->relativeTo(other: $fromPath); $this->assertSame($expectedUnix, $relativePath->toString()); } @@ -194,14 +194,14 @@ public function it_should_handle_relative_paths_with_mixed_slashes( public function it_should_split_mixed_slash_paths_into_parts(): void { // Test with Windows separator - FSPath::setDirectorySeparator('\\'); - $path = FSPath::create('C:/Users\\test/documents\\file.txt'); + FSPath::setDirectorySeparator(separator: '\\'); + $path = FSPath::create(path: 'C:/Users\\test/documents\\file.txt'); $parts = $path->parts(); $this->assertSame(['C:', 'Users', 'test', 'documents', 'file.txt'], $parts); // Test with Unix separator - FSPath::setDirectorySeparator('/'); - $path = FSPath::create('C:/Users\\test/documents\\file.txt'); + FSPath::setDirectorySeparator(separator: '/'); + $path = FSPath::create(path: 'C:/Users\\test/documents\\file.txt'); $parts = $path->parts(); $this->assertSame(['C:', 'Users', 'test', 'documents', 'file.txt'], $parts); } @@ -210,19 +210,19 @@ public function it_should_split_mixed_slash_paths_into_parts(): void public function it_should_normalize_path_with_many_mixed_slashes(): void { // Test with Windows separator - FSPath::setDirectorySeparator('\\'); - $path = FSPath::create('C:\\\\Users//test\\/documents///file.txt'); + FSPath::setDirectorySeparator(separator: '\\'); + $path = FSPath::create(path: 'C:\\\\Users//test\\/documents///file.txt'); $this->assertSame('C:\\Users\\test\\documents\\file.txt', $path->toString()); // Test with Unix separator - FSPath::setDirectorySeparator('/'); - $path = FSPath::create('C:\\\\Users//test\\/documents///file.txt'); + FSPath::setDirectorySeparator(separator: '/'); + $path = FSPath::create(path: 'C:\\\\Users//test\\/documents///file.txt'); $this->assertSame('C:/Users/test/documents/file.txt', $path->toString()); } protected function tearDown(): void { // Always reset directory separator at the end of each test - FSPath::setDirectorySeparator(null); + FSPath::setDirectorySeparator(); } } diff --git a/tests/src/Unit/Application/FSPathWindowsTest.php b/tests/src/Unit/Application/FSPathWindowsTest.php index 973c0dcf..8f40072e 100644 --- a/tests/src/Unit/Application/FSPathWindowsTest.php +++ b/tests/src/Unit/Application/FSPathWindowsTest.php @@ -53,7 +53,7 @@ public static function provideRelativePathTests(): \Generator #[Test] public function it_should_create_path_from_string(): void { - $path = FSPath::create('C:\\Users\\test'); + $path = FSPath::create(path: 'C:\\Users\\test'); $this->assertSame('C:\\Users\\test', $path->toString()); } @@ -61,7 +61,7 @@ public function it_should_create_path_from_string(): void #[Test] public function it_should_join_paths_correctly(): void { - $base = FSPath::create('C:\\Users'); + $base = FSPath::create(path: 'C:\\Users'); $joined = $base->join('test', 'documents'); $this->assertSame('C:\\Users\\test\\documents', $joined->toString()); @@ -76,9 +76,9 @@ public function it_should_join_paths_correctly(): void #[Test] public function it_should_handle_name_operations(): void { - $path = FSPath::create('C:\\Users\\test\\document.txt'); + $path = FSPath::create(path: 'C:\\Users\\test\\document.txt'); - $newPath = $path->withName('new.txt'); + $newPath = $path->withName(name: 'new.txt'); $this->assertSame('C:\\Users\\test\\new.txt', $newPath->toString()); $extension = $path->extension(); @@ -88,22 +88,22 @@ public function it_should_handle_name_operations(): void #[Test] public function it_should_handle_extension_operations(): void { - $path = FSPath::create('C:\\Users\\test\\document.txt'); + $path = FSPath::create(path: 'C:\\Users\\test\\document.txt'); - $newPath = $path->withExt('md'); + $newPath = $path->withExt(suffix: 'md'); $this->assertSame('C:\\Users\\test\\document.md', $newPath->toString()); - $newPath = $path->withExt('.md'); + $newPath = $path->withExt(suffix: '.md'); $this->assertSame('C:\\Users\\test\\document.md', $newPath->toString()); - $newPath = $path->withStem('report'); + $newPath = $path->withStem(stem: 'report'); $this->assertSame('C:\\Users\\test\\report.txt', $newPath->toString()); } #[Test] public function it_should_get_parent_directory(): void { - $path = FSPath::create('C:\\Users\\test\\document.txt'); + $path = FSPath::create(path: 'C:\\Users\\test\\document.txt'); $parent = $path->parent(); $this->assertSame('C:\\Users\\test', $parent->toString()); @@ -115,25 +115,25 @@ public function it_should_get_parent_directory(): void #[Test] public function it_should_handle_root_paths(): void { - $root = FSPath::create('C:\\'); + $root = FSPath::create(path: 'C:\\'); // Root parent should be itself $this->assertSame('C:\\', $root->parent()->toString()); // These operations should not change a root path - $this->assertSame('C:\\', $root->withName('test')->toString()); - $this->assertSame('C:\\', $root->withExt('txt')->toString()); - $this->assertSame('C:\\', $root->withStem('test')->toString()); + $this->assertSame('C:\\', $root->withName(name: 'test')->toString()); + $this->assertSame('C:\\', $root->withExt(suffix: 'txt')->toString()); + $this->assertSame('C:\\', $root->withStem(stem: 'test')->toString()); } #[Test] public function it_should_check_path_types(): void { - $absolutePath = FSPath::create('C:\\Users\\test'); + $absolutePath = FSPath::create(path: 'C:\\Users\\test'); $this->assertTrue($absolutePath->isAbsolute()); $this->assertFalse($absolutePath->isRelative()); - $relativePath = FSPath::create('Users\\test'); + $relativePath = FSPath::create(path: 'Users\\test'); $this->assertFalse($relativePath->isAbsolute()); $this->assertTrue($relativePath->isRelative()); } @@ -142,10 +142,10 @@ public function it_should_check_path_types(): void #[DataProvider('provideRelativePathTests')] public function it_should_handle_relative_paths(string $from, string $to, string $expected): void { - $fromPath = FSPath::create($from); - $toPath = FSPath::create($to); + $fromPath = FSPath::create(path: $from); + $toPath = FSPath::create(path: $to); - $relativePath = $toPath->relativeTo($fromPath); + $relativePath = $toPath->relativeTo(other: $fromPath); $this->assertSame($expected, $relativePath->toString()); } @@ -153,22 +153,22 @@ public function it_should_handle_relative_paths(string $from, string $to, string public function it_should_normalize_paths(): void { // Mixed separators - $path = FSPath::create('C:/Users\\test/documents'); + $path = FSPath::create(path: 'C:/Users\\test/documents'); $this->assertSame('C:\\Users\\test\\documents', $path->toString()); // Double separators - $path = FSPath::create('C:\\\\Users\\\\\\test'); + $path = FSPath::create(path: 'C:\\\\Users\\\\\\test'); $this->assertSame('C:\\Users\\test', $path->toString()); // Dot segments - $path = FSPath::create('C:\\Users\\.\\test\\..\\admin'); + $path = FSPath::create(path: 'C:\\Users\\.\\test\\..\\admin'); $this->assertSame('C:\\Users\\admin', $path->toString()); } #[Test] public function it_should_split_path_into_parts(): void { - $path = FSPath::create('C:\\Users\\test\\documents\\file.txt'); + $path = FSPath::create(path: 'C:\\Users\\test\\documents\\file.txt'); $parts = $path->parts(); $this->assertSame(['C:', 'Users', 'test', 'documents', 'file.txt'], $parts); @@ -177,7 +177,7 @@ public function it_should_split_path_into_parts(): void #[Test] public function it_should_handle_stringable_interface(): void { - $path = FSPath::create('C:\\Users\\test'); + $path = FSPath::create(path: 'C:\\Users\\test'); $this->assertSame('C:\\Users\\test', (string) $path); $this->assertSame($path->toString(), (string) $path); @@ -186,7 +186,7 @@ public function it_should_handle_stringable_interface(): void #[Test] public function it_should_handle_empty_paths(): void { - $path = FSPath::create(''); + $path = FSPath::create(); $this->assertSame('.', $path->toString()); $this->assertFalse($path->isAbsolute()); @@ -197,15 +197,15 @@ public function it_should_handle_empty_paths(): void public function it_should_properly_add_extension_prefix_when_changing_stem(): void { // Test specifically for the bug where withStem doesn't add the period before extension - $path = FSPath::create('C:\\Users\\test\\document.txt'); + $path = FSPath::create(path: 'C:\\Users\\test\\document.txt'); - $newPath = $path->withStem('report'); + $newPath = $path->withStem(stem: 'report'); $this->assertSame('C:\\Users\\test\\report.txt', $newPath->toString()); // Also test with no extension - $path = FSPath::create('C:\\Users\\test\\document'); + $path = FSPath::create(path: 'C:\\Users\\test\\document'); - $newPath = $path->withStem('report'); + $newPath = $path->withStem(stem: 'report'); $this->assertSame('C:\\Users\\test\\report', $newPath->toString()); } @@ -213,7 +213,7 @@ protected function setUp(): void { // Override directory separator for testing on non-Windows systems if (DIRECTORY_SEPARATOR !== self::WINDOWS_DIRECTORY_SEPARATOR) { - FSPath::setDirectorySeparator(self::WINDOWS_DIRECTORY_SEPARATOR); + FSPath::setDirectorySeparator(separator: self::WINDOWS_DIRECTORY_SEPARATOR); $this->isSeparatorOverridden = true; } } @@ -222,7 +222,7 @@ protected function tearDown(): void { // Reset directory separator if it was overridden if ($this->isSeparatorOverridden) { - FSPath::setDirectorySeparator(null); + FSPath::setDirectorySeparator(); } } } diff --git a/tests/src/Unit/DirectoriesTest.php b/tests/src/Unit/DirectoriesTest.php index 1f3e3878..1fdb76d2 100644 --- a/tests/src/Unit/DirectoriesTest.php +++ b/tests/src/Unit/DirectoriesTest.php @@ -109,7 +109,7 @@ public function it_should_create_new_instance_with_updated_root_path(): void jsonSchemaPath: '/test/schema', ); - $newDirs = $dirs->withRootPath('/new/root'); + $newDirs = $dirs->withRootPath(rootPath: '/new/root'); // Verify original instance is unchanged $this->assertSame('/test/root', $dirs->rootPath); @@ -131,7 +131,7 @@ public function it_should_return_same_instance_when_root_path_is_null(): void jsonSchemaPath: '/test/schema', ); - $newDirs = $dirs->withRootPath(null); + $newDirs = $dirs->withRootPath(); $this->assertSame($dirs, $newDirs); } @@ -146,7 +146,7 @@ public function it_should_create_new_instance_with_updated_config_path(): void jsonSchemaPath: '/test/schema', ); - $newDirs = $dirs->withConfigPath('/new/config'); + $newDirs = $dirs->withConfigPath(configPath: '/new/config'); // Verify original instance is unchanged $this->assertSame('/test/config', $dirs->configPath); @@ -168,7 +168,7 @@ public function it_should_return_same_instance_when_config_path_is_null(): void jsonSchemaPath: '/test/schema', ); - $newDirs = $dirs->withConfigPath(null); + $newDirs = $dirs->withConfigPath(); $this->assertSame($dirs, $newDirs); } @@ -183,7 +183,7 @@ public function it_should_create_new_instance_with_env_file(): void jsonSchemaPath: '/test/schema', ); - $newDirs = $dirs->withEnvFile('.env.test'); + $newDirs = $dirs->withEnvFile(envFileName: '.env.test'); // Verify original instance is unchanged $this->assertNull($dirs->envFilePath); @@ -202,7 +202,7 @@ public function it_should_return_same_instance_when_env_file_is_null(): void jsonSchemaPath: '/test/schema', ); - $newDirs = $dirs->withEnvFile(null); + $newDirs = $dirs->withEnvFile(); $this->assertSame($dirs, $newDirs); } @@ -243,7 +243,7 @@ public function it_should_determine_root_path_from_config_path(): void // Create a temporary directory for testing $tempDir = $this->createTempDir(); $configDir = $tempDir . '/config'; - \mkdir($configDir); + \mkdir(directory: $configDir); $dirs = new Directories( rootPath: '/test/root', @@ -253,16 +253,16 @@ public function it_should_determine_root_path_from_config_path(): void ); // Test with absolute config path to existing directory - $newDirs = $dirs->determineRootPath($configDir); + $newDirs = $dirs->determineRootPath(configPath: $configDir); $this->assertSame($configDir, $newDirs->rootPath); $this->assertSame($configDir, $newDirs->configPath); // Test with absolute config path to existing file $configFile = $tempDir . '/config.json'; - \file_put_contents($configFile, '{}'); + \file_put_contents(filename: $configFile, data: '{}'); $this->registerTempFile($configFile); - $newDirs = $dirs->determineRootPath($configFile); + $newDirs = $dirs->determineRootPath(configPath: $configFile); $this->assertSame($tempDir, $newDirs->rootPath); $this->assertSame($configFile, $newDirs->configPath); } @@ -273,7 +273,7 @@ public function it_should_resolve_relative_config_path_against_root_path(): void // Create a temporary directory structure $tempDir = $this->createTempDir(); $configDir = $tempDir . '/config'; - \mkdir($configDir); + \mkdir(directory: $configDir); $dirs = new Directories( rootPath: $tempDir, @@ -283,7 +283,7 @@ public function it_should_resolve_relative_config_path_against_root_path(): void ); // Test with relative config path - $newDirs = $dirs->determineRootPath('config'); + $newDirs = $dirs->determineRootPath(configPath: 'config'); $this->assertSame($configDir, $newDirs->rootPath); $this->assertSame($configDir, $newDirs->configPath); } @@ -298,7 +298,7 @@ public function it_should_return_same_instance_when_config_path_is_null_in_deter jsonSchemaPath: '/test/schema', ); - $newDirs = $dirs->determineRootPath(null); + $newDirs = $dirs->determineRootPath(); $this->assertSame($dirs, $newDirs); } @@ -313,7 +313,7 @@ public function it_should_return_same_instance_when_inline_config_is_provided(): jsonSchemaPath: '/test/schema', ); - $newDirs = $dirs->determineRootPath('/path/to/config.json', '{"inline": "config"}'); + $newDirs = $dirs->determineRootPath(configPath: '/path/to/config.json', inlineConfig: '{"inline": "config"}'); $this->assertSame($dirs, $newDirs); } @@ -329,7 +329,7 @@ public function it_should_return_same_instance_when_config_dir_does_not_exist(): ); // Non-existent path - $newDirs = $dirs->determineRootPath('/non/existent/path'); + $newDirs = $dirs->determineRootPath(configPath: '/non/existent/path'); $this->assertSame($dirs, $newDirs); } diff --git a/tests/src/Unit/Document/Compiler/DocumentCompilerTest.php b/tests/src/Unit/Document/Compiler/DocumentCompilerTest.php index 672a5001..7e0b4eff 100644 --- a/tests/src/Unit/Document/Compiler/DocumentCompilerTest.php +++ b/tests/src/Unit/Document/Compiler/DocumentCompilerTest.php @@ -56,10 +56,10 @@ public function it_should_compile_document_with_basic_content(): void $content = "# Test Document", ); - $compiled = $this->compiler->compile($document); + $compiled = $this->compiler->compile(document: $document); $this->assertEquals($content, (string) $compiled->content); - $this->assertEquals(0, \count($compiled->errors)); + $this->assertEquals(0, \count(value: $compiled->errors)); } #[Test] @@ -81,10 +81,10 @@ public function it_should_skip_compilation_if_file_exists_and_overwrite_is_false ->expects($this->never()) ->method('write'); - $compiled = $this->compiler->compile($document); + $compiled = $this->compiler->compile(document: $document); $this->assertEquals("", (string) $compiled->content); - $this->assertEquals(0, \count($compiled->errors)); + $this->assertEquals(0, \count(value: $compiled->errors)); } #[Test] @@ -99,7 +99,7 @@ public function it_should_handle_source_errors(): void $source = $this->createMock(SourceInterface::class); $source ->method('parseContent') - ->willThrowException(new \RuntimeException('Source error')); + ->willThrowException(new \RuntimeException(message: 'Source error')); $document = $document->addSource($source); @@ -109,10 +109,10 @@ public function it_should_handle_source_errors(): void ->with('/base/path/output.txt') ->willReturn(false); - $compiled = $this->compiler->compile($document); + $compiled = $this->compiler->compile(document: $document); $this->assertEquals("# Test Document", (string) $compiled->content); - $this->assertEquals(1, \count($compiled->errors)); + $this->assertEquals(1, \count(value: $compiled->errors)); $this->assertInstanceOf(SourceError::class, $compiled->errors->getIterator()[0]); } @@ -139,10 +139,10 @@ public function it_should_include_document_tags(): void $content = "# Test Document\n\ntag1, tag2\n", ); - $compiled = $this->compiler->compile($document); + $compiled = $this->compiler->compile(document: $document); $this->assertEquals($content, (string) $compiled->content); - $this->assertEquals(0, \count($compiled->errors)); + $this->assertEquals(0, \count(value: $compiled->errors)); } #[Test] @@ -180,10 +180,10 @@ public function it_should_process_multiple_sources(): void $content = "# Test Document\nContent from source 1\nContent from source 2", ); - $compiled = $this->compiler->compile($document); + $compiled = $this->compiler->compile(document: $document); $this->assertEquals($content, (string) $compiled->content); - $this->assertEquals(0, \count($compiled->errors)); + $this->assertEquals(0, \count(value: $compiled->errors)); } #[Test] @@ -210,10 +210,10 @@ public function it_should_include_source_description(): void $content = "# Test Document\n_SOURCE: Source Description_\nSource content", ); - $compiled = $this->compiler->compile($document); + $compiled = $this->compiler->compile(document: $document); $this->assertEquals($content, (string) $compiled->content); - $this->assertEquals(0, \count($compiled->errors)); + $this->assertEquals(0, \count(value: $compiled->errors)); } #[Test] @@ -228,20 +228,20 @@ public function it_should_handle_multiple_source_errors(): void $source1 = $this->createMock(SourceInterface::class); $source1 ->method('parseContent') - ->willThrowException(new \RuntimeException('Error 1')); + ->willThrowException(new \RuntimeException(message: 'Error 1')); $source2 = $this->createMock(SourceInterface::class); $source2 ->method('parseContent') - ->willThrowException(new \RuntimeException('Error 2')); + ->willThrowException(new \RuntimeException(message: 'Error 2')); $document = $document->addSource($source1)->addSource($source2); - $compiled = $this->compiler->compile($document); + $compiled = $this->compiler->compile(document: $document); $this->assertEquals("# Test Document", (string) $compiled->content); - $this->assertEquals(2, \count($compiled->errors)); - $errors = \iterator_to_array($compiled->errors->getIterator()); + $this->assertEquals(2, \count(value: $compiled->errors)); + $errors = \iterator_to_array(iterator: $compiled->errors->getIterator()); $this->assertInstanceOf(SourceError::class, $errors[0]); $this->assertInstanceOf(SourceError::class, $errors[1]); $this->assertEquals('Error 1', $errors[0]->exception->getMessage()); @@ -265,10 +265,10 @@ public function it_should_compile_empty_document(): void $content = "# Empty Document", ); - $compiled = $this->compiler->compile($document); + $compiled = $this->compiler->compile(document: $document); $this->assertEquals($content, (string) $compiled->content); - $this->assertEquals(0, \count($compiled->errors)); + $this->assertEquals(0, \count(value: $compiled->errors)); } protected function setUp(): void diff --git a/tests/src/Unit/Document/DocumentTest.php b/tests/src/Unit/Document/DocumentTest.php index c817bcc9..1610ae04 100644 --- a/tests/src/Unit/Document/DocumentTest.php +++ b/tests/src/Unit/Document/DocumentTest.php @@ -75,7 +75,7 @@ public function it_should_include_source_tags_when_getting_tags(): void $source->method('getTags')->willReturn(['source-tag']); $document = $this->document->addSource($source); - $tags = $document->getTags(true); + $tags = $document->getTags(); $this->assertCount(1, $tags); $this->assertContains('source-tag', $tags); @@ -88,7 +88,7 @@ public function it_should_not_include_source_tags_when_getting_tags(): void $source->method('getTags')->willReturn(['source-tag']); $document = $this->document->addSource($source); - $tags = $document->getTags(false); + $tags = $document->getTags(includeSources: false); $this->assertEmpty($tags); } @@ -133,7 +133,7 @@ public function it_should_handle_modifiers_with_context(): void #[Test] public function it_should_handle_modifiers_from_array(): void { - $modifier = Modifier::from([ + $modifier = Modifier::from(data: [ 'name' => 'test-modifier', 'options' => ['key' => 'value'], ]); @@ -149,7 +149,7 @@ public function it_should_handle_modifiers_from_array(): void #[Test] public function it_should_handle_modifiers_from_string(): void { - $modifier = Modifier::from('test-modifier'); + $modifier = Modifier::from(data: 'test-modifier'); $document = $this->document->addModifier($modifier); $modifiers = $document->getModifiers(); @@ -195,7 +195,7 @@ public function it_should_handle_source_description(): void protected function setUp(): void { - $this->fixturesDir = \dirname(__DIR__, 3) . '/fixtures/Document'; + $this->fixturesDir = \dirname(path: __DIR__, levels: 3) . '/fixtures/Document'; $this->document = Document::create( description: 'Test Document', outputPath: $this->fixturesDir . '/output.txt', diff --git a/tests/src/Unit/Fetcher/FileSourceFetcherTest.php b/tests/src/Unit/Fetcher/FileSourceFetcherTest.php index cace2389..79a99589 100644 --- a/tests/src/Unit/Fetcher/FileSourceFetcherTest.php +++ b/tests/src/Unit/Fetcher/FileSourceFetcherTest.php @@ -23,7 +23,7 @@ class FileSourceFetcherTest extends TestCase public function it_should_not_support_other_sources(): void { $source = $this->createMock(SourceInterface::class); - $this->assertFalse($this->fetcher->supports($source)); + $this->assertFalse($this->fetcher->supports(source: $source)); } #[Test] @@ -34,7 +34,7 @@ public function it_should_throw_exception_for_invalid_source_type(): void $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Source must be an instance of FileSource'); - $this->fetcher->fetch($source, new ModifiersApplier([])); + $this->fetcher->fetch(source: $source, modifiersApplier: new ModifiersApplier(modifiers: [])); } protected function setUp(): void diff --git a/tests/src/Unit/Fetcher/FileTreeBuilderTest.php b/tests/src/Unit/Fetcher/FileTreeBuilderTest.php index f18ac6d0..dda1431b 100644 --- a/tests/src/Unit/Fetcher/FileTreeBuilderTest.php +++ b/tests/src/Unit/Fetcher/FileTreeBuilderTest.php @@ -22,10 +22,10 @@ public function it_should_build_tree_from_list_of_files(): void '/root/project/tests/file4.php', ]; $basePath = '/root/project'; - $expected = $this->treeBuilder->buildTree($files, $basePath); + $expected = $this->treeBuilder->buildTree(files: $files, basePath: $basePath); // Get the actual output to match against - $result = $this->treeBuilder->buildTree($files, $basePath); + $result = $this->treeBuilder->buildTree(files: $files, basePath: $basePath); // We'll verify tree structure exists with all the files rather than exact format $this->assertStringContainsString('└── src', $result); @@ -44,7 +44,7 @@ public function it_should_handle_empty_file_list(): void { $files = []; $basePath = '/root/project'; - $result = $this->treeBuilder->buildTree($files, $basePath); + $result = $this->treeBuilder->buildTree(files: $files, basePath: $basePath); // Check that result contains the "No files found" message or is empty $this->assertTrue( @@ -62,7 +62,7 @@ public function it_should_normalize_paths_without_base_path(): void 'tests/file3.php', ]; $basePath = ''; - $result = $this->treeBuilder->buildTree($files, $basePath); + $result = $this->treeBuilder->buildTree(files: $files, basePath: $basePath); // Verify tree structure contains all the files rather than exact format $this->assertStringContainsString('src', $result); diff --git a/tests/src/Unit/Fetcher/TextSourceFetcherTest.php b/tests/src/Unit/Fetcher/TextSourceFetcherTest.php index 6f3ac149..8a6abee3 100644 --- a/tests/src/Unit/Fetcher/TextSourceFetcherTest.php +++ b/tests/src/Unit/Fetcher/TextSourceFetcherTest.php @@ -19,14 +19,14 @@ class TextSourceFetcherTest extends TestCase public function it_should_support_text_source(): void { $source = new TextSource(content: 'Sample content'); - $this->assertTrue($this->fetcher->supports($source)); + $this->assertTrue($this->fetcher->supports(source: $source)); } #[Test] public function it_should_not_support_other_sources(): void { $source = $this->createMock(SourceInterface::class); - $this->assertFalse($this->fetcher->supports($source)); + $this->assertFalse($this->fetcher->supports(source: $source)); } #[Test] @@ -40,7 +40,7 @@ public function it_should_fetch_content_from_text_source(): void "\n" . "------------------------------------------------------------\n"; - $this->assertEquals($expected, $this->fetcher->fetch($source, new ModifiersApplier([]))); + $this->assertEquals($expected, $this->fetcher->fetch(source: $source, modifiersApplier: new ModifiersApplier(modifiers: []))); } #[Test] @@ -51,7 +51,7 @@ public function it_should_throw_exception_for_invalid_source_type(): void $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Source must be an instance of TextSource'); - $this->fetcher->fetch($source, new ModifiersApplier([])); + $this->fetcher->fetch(source: $source, modifiersApplier: new ModifiersApplier(modifiers: [])); } protected function setUp(): void diff --git a/tests/src/Unit/Lib/Html/HtmlCleanerTest.php b/tests/src/Unit/Lib/Html/HtmlCleanerTest.php index eeab780f..0ab123e7 100644 --- a/tests/src/Unit/Lib/Html/HtmlCleanerTest.php +++ b/tests/src/Unit/Lib/Html/HtmlCleanerTest.php @@ -25,7 +25,7 @@ public function it_should_clean_html_content(): void ->willReturn($expectedMarkdown); $cleaner = new HtmlCleaner(htmlConverter: $htmlConverter); - $result = $cleaner->clean($html); + $result = $cleaner->clean(html: $html); $this->assertEquals($expectedMarkdown, $result); } @@ -41,7 +41,7 @@ public function it_should_handle_empty_html(): void ->method('convert'); $cleaner = new HtmlCleaner(htmlConverter: $htmlConverter); - $result = $cleaner->clean($html); + $result = $cleaner->clean(html: $html); $this->assertEquals('', $result); } @@ -52,7 +52,7 @@ public function it_should_use_default_html_converter_if_not_provided(): void $html = '

Test Title

This is a test paragraph

'; $cleaner = new HtmlCleaner(); - $result = $cleaner->clean($html); + $result = $cleaner->clean(html: $html); // Just verify that conversion happens without errors $this->assertIsString($result); diff --git a/tests/src/Unit/Lib/Sanitizer/CommentInsertionRuleTest.php b/tests/src/Unit/Lib/Sanitizer/CommentInsertionRuleTest.php index b5427310..767d2ce5 100644 --- a/tests/src/Unit/Lib/Sanitizer/CommentInsertionRuleTest.php +++ b/tests/src/Unit/Lib/Sanitizer/CommentInsertionRuleTest.php @@ -13,7 +13,7 @@ class CommentInsertionRuleTest extends TestCase #[Test] public function it_should_return_correct_name(): void { - $rule = new CommentInsertionRule('test-rule'); + $rule = new CommentInsertionRule(name: 'test-rule'); $this->assertEquals('test-rule', $rule->getName()); } @@ -28,7 +28,7 @@ public function it_should_apply_file_header_comment(): void $content = "assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -42,7 +42,7 @@ public function it_should_apply_multiline_file_header_comment(): void $content = "assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -56,7 +56,7 @@ classComment: 'This is a class comment', $content = "assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -70,7 +70,7 @@ public function it_should_apply_method_comment(): void $content = "assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -83,11 +83,11 @@ public function it_should_apply_random_comments(): void ); $content = "Line 1\nLine 2\nLine 3\nLine 4"; - $result = $rule->apply($content); + $result = $rule->apply(content: $content); // Since the random comment selection is non-deterministic, we can only check // that the number of lines has increased as expected - $this->assertGreaterThan(\strlen($content), \strlen($result)); + $this->assertGreaterThan(\strlen(string: $content), \strlen(string: $result)); $this->assertStringContainsString('// Random comment', $result); } @@ -104,7 +104,7 @@ classComment: 'Class comment', ); $content = "apply($content); + $result = $rule->apply(content: $content); $this->assertStringContainsString('// File header', $result); $this->assertStringContainsString('// Class comment', $result); diff --git a/tests/src/Unit/Lib/Sanitizer/ContextSanitizerTest.php b/tests/src/Unit/Lib/Sanitizer/ContextSanitizerTest.php index e27633bb..ca6e8e84 100644 --- a/tests/src/Unit/Lib/Sanitizer/ContextSanitizerTest.php +++ b/tests/src/Unit/Lib/Sanitizer/ContextSanitizerTest.php @@ -27,7 +27,7 @@ public function it_should_initialize_with_provided_rules(): void $rule2 = $this->createMock(RuleInterface::class); $rule2->method('getName')->willReturn('rule2'); - $sanitizer = new ContextSanitizer([ + $sanitizer = new ContextSanitizer(rules: [ 'rule1' => $rule1, 'rule2' => $rule2, ]); @@ -45,7 +45,7 @@ public function it_should_add_rule_correctly(): void $rule = $this->createMock(RuleInterface::class); $rule->method('getName')->willReturn('test-rule'); - $result = $sanitizer->addRule($rule); + $result = $sanitizer->addRule(rule: $rule); $this->assertSame($sanitizer, $result); $this->assertCount(1, $sanitizer->getRules()); @@ -63,8 +63,8 @@ public function it_should_add_multiple_rules_correctly(): void $rule2 = $this->createMock(RuleInterface::class); $rule2->method('getName')->willReturn('rule2'); - $sanitizer->addRule($rule1); - $sanitizer->addRule($rule2); + $sanitizer->addRule(rule: $rule1); + $sanitizer->addRule(rule: $rule2); $this->assertCount(2, $sanitizer->getRules()); $this->assertSame($rule1, $sanitizer->getRules()['rule1']); @@ -82,8 +82,8 @@ public function it_should_overwrite_existing_rule_with_same_name(): void $rule2 = $this->createMock(RuleInterface::class); $rule2->method('getName')->willReturn('same-name'); - $sanitizer->addRule($rule1); - $sanitizer->addRule($rule2); + $sanitizer->addRule(rule: $rule1); + $sanitizer->addRule(rule: $rule2); $this->assertCount(1, $sanitizer->getRules()); $this->assertSame($rule2, $sanitizer->getRules()['same-name']); @@ -98,7 +98,7 @@ public function it_should_return_all_rules(): void $rule2 = $this->createMock(RuleInterface::class); $rule2->method('getName')->willReturn('rule2'); - $sanitizer = new ContextSanitizer([ + $sanitizer = new ContextSanitizer(rules: [ 'rule1' => $rule1, 'rule2' => $rule2, ]); @@ -116,7 +116,7 @@ public function it_should_not_modify_content_with_no_rules(): void $sanitizer = new ContextSanitizer(); $content = "This content should remain unchanged"; - $this->assertEquals($content, $sanitizer->sanitize($content)); + $this->assertEquals($content, $sanitizer->sanitize(content: $content)); } #[Test] @@ -126,10 +126,10 @@ public function it_should_apply_single_rule_correctly(): void $rule->method('getName')->willReturn('test-rule'); $rule->method('apply')->willReturnCallback(static fn($content) => $content . ' (sanitized)'); - $sanitizer = new ContextSanitizer(['test-rule' => $rule]); + $sanitizer = new ContextSanitizer(rules: ['test-rule' => $rule]); $content = "Original content"; - $this->assertEquals("Original content (sanitized)", $sanitizer->sanitize($content)); + $this->assertEquals("Original content (sanitized)", $sanitizer->sanitize(content: $content)); } #[Test] @@ -143,14 +143,14 @@ public function it_should_apply_multiple_rules_correctly(): void $rule2->method('getName')->willReturn('rule2'); $rule2->method('apply')->willReturnCallback(static fn($content) => $content . ' (rule2)'); - $sanitizer = new ContextSanitizer([ + $sanitizer = new ContextSanitizer(rules: [ 'rule1' => $rule1, 'rule2' => $rule2, ]); $content = "Original content"; - $this->assertEquals("Original content (rule1) (rule2)", $sanitizer->sanitize($content)); + $this->assertEquals("Original content (rule1) (rule2)", $sanitizer->sanitize(content: $content)); } #[Test] @@ -166,11 +166,11 @@ public function it_should_apply_rules_in_order_of_addition(): void // Add rules in specific order $sanitizer = new ContextSanitizer(); - $sanitizer->addRule($rule1); - $sanitizer->addRule($rule2); + $sanitizer->addRule(rule: $rule1); + $sanitizer->addRule(rule: $rule2); $content = "Original"; - $this->assertEquals("Original (first) (second)", $sanitizer->sanitize($content)); + $this->assertEquals("Original (first) (second)", $sanitizer->sanitize(content: $content)); } } diff --git a/tests/src/Unit/Lib/Sanitizer/KeywordRemovalRuleTest.php b/tests/src/Unit/Lib/Sanitizer/KeywordRemovalRuleTest.php index 5419b5b3..34afaf1e 100644 --- a/tests/src/Unit/Lib/Sanitizer/KeywordRemovalRuleTest.php +++ b/tests/src/Unit/Lib/Sanitizer/KeywordRemovalRuleTest.php @@ -13,17 +13,17 @@ class KeywordRemovalRuleTest extends TestCase #[Test] public function it_should_return_correct_name(): void { - $rule = new KeywordRemovalRule('test-rule', ['keyword']); + $rule = new KeywordRemovalRule(name: 'test-rule', keywords: ['keyword']); $this->assertEquals('test-rule', $rule->getName()); } #[Test] public function it_should_not_modify_content_with_empty_keywords(): void { - $rule = new KeywordRemovalRule('empty-keywords', []); + $rule = new KeywordRemovalRule(name: 'empty-keywords', keywords: []); $content = "This content should remain unchanged"; - $this->assertEquals($content, $rule->apply($content)); + $this->assertEquals($content, $rule->apply(content: $content)); } #[Test] @@ -38,7 +38,7 @@ public function it_should_remove_lines_with_single_keyword(): void $content = "Line with no match\nLine with secret keyword\nAnother normal line"; $expected = "Line with no match\n[REMOVED]\nAnother normal line"; - $this->assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -53,7 +53,7 @@ public function it_should_remove_lines_with_multiple_keywords(): void $content = "Line with secret\nLine with password\nLine with key\nNormal line"; $expected = "[REMOVED]\n[REMOVED]\n[REMOVED]\nNormal line"; - $this->assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -69,7 +69,7 @@ public function it_should_use_custom_replacement_text(): void $content = "Line with no match\nLine with secret keyword\nAnother normal line"; $expected = "Line with no match\n[REDACTED]\nAnother normal line"; - $this->assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -85,7 +85,7 @@ public function it_should_replace_keywords_without_removing_lines(): void $content = "Line with no match\nLine with secret keyword\nAnother normal line"; $expected = "Line with no match\nLine with [REDACTED] keyword\nAnother normal line"; - $this->assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -101,7 +101,7 @@ public function it_should_respect_case_sensitive_matching(): void $content = "Line with Secret\nLine with secret\nNormal line"; $expected = "[REMOVED]\nLine with secret\nNormal line"; - $this->assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -117,7 +117,7 @@ public function it_should_respect_case_insensitive_matching(): void $content = "Line with Secret\nLine with secret\nNormal line"; $expected = "[REMOVED]\n[REMOVED]\nNormal line"; - $this->assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -133,6 +133,6 @@ public function it_should_replace_multiple_keywords_in_same_line(): void $content = "Line with secret and password\nNormal line"; $expected = "Line with [REDACTED] and [REDACTED]\nNormal line"; - $this->assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } } diff --git a/tests/src/Unit/Lib/Sanitizer/RegexReplacementRuleTest.php b/tests/src/Unit/Lib/Sanitizer/RegexReplacementRuleTest.php index 78a25516..1a5d56d1 100644 --- a/tests/src/Unit/Lib/Sanitizer/RegexReplacementRuleTest.php +++ b/tests/src/Unit/Lib/Sanitizer/RegexReplacementRuleTest.php @@ -13,17 +13,17 @@ class RegexReplacementRuleTest extends TestCase #[Test] public function it_should_return_correct_name(): void { - $rule = new RegexReplacementRule('test-rule', []); + $rule = new RegexReplacementRule(name: 'test-rule', patterns: []); $this->assertEquals('test-rule', $rule->getName()); } #[Test] public function it_should_not_modify_content_with_empty_patterns(): void { - $rule = new RegexReplacementRule('empty-patterns', []); + $rule = new RegexReplacementRule(name: 'empty-patterns', patterns: []); $content = "This content should remain unchanged"; - $this->assertEquals($content, $rule->apply($content)); + $this->assertEquals($content, $rule->apply(content: $content)); } #[Test] @@ -37,7 +37,7 @@ public function it_should_apply_single_regex_pattern(): void $content = "Contact us at test@example.com for more information"; $expected = "Contact us at [EMAIL_REMOVED] for more information"; - $this->assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -54,7 +54,7 @@ public function it_should_apply_multiple_regex_patterns(): void $content = "Contact us at test@example.com or visit our server at 192.168.1.1"; $expected = "Contact us at [EMAIL_REMOVED] or visit our server at [IP_ADDRESS_REMOVED]"; - $this->assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -70,7 +70,7 @@ public function it_should_handle_capture_groups_correctly(): void $content = "config = { password = \"supersecret123\" }"; $expected = "config = { password=\"[REDACTED]\" }"; - $this->assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -86,7 +86,7 @@ public function it_should_work_with_multiline_content(): void $content = "function test() {\n /* This is a\n multiline comment */\n return true;\n}"; $expected = "function test() {\n [COMMENT_REMOVED]\n return true;\n}"; - $this->assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -103,7 +103,7 @@ public function it_should_handle_complex_regex_patterns(): void $content = "Card: 1234 5678 9012 3456, Phone: (123) 456-7890"; $expected = "Card: [CREDIT_CARD_REMOVED], Phone: ([PHONE_NUMBER_REMOVED]"; - $this->assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } #[Test] @@ -118,7 +118,7 @@ public function it_should_return_unchanged_content_with_no_matches(): void $content = "This content has no email addresses"; - $this->assertEquals($content, $rule->apply($content)); + $this->assertEquals($content, $rule->apply(content: $content)); } #[Test] @@ -135,6 +135,6 @@ public function it_should_handle_overlapping_patterns_correctly(): void $content = "The code is secret123key and secret456code"; $expected = "The code is [SECRET_KEY_REMOVED] and [SECRET_CODE_REMOVED]"; - $this->assertEquals($expected, $rule->apply($content)); + $this->assertEquals($expected, $rule->apply(content: $content)); } } diff --git a/tests/src/Unit/Lib/Sanitizer/RuleFactoryTest.php b/tests/src/Unit/Lib/Sanitizer/RuleFactoryTest.php index c42e5b66..e66f9e78 100644 --- a/tests/src/Unit/Lib/Sanitizer/RuleFactoryTest.php +++ b/tests/src/Unit/Lib/Sanitizer/RuleFactoryTest.php @@ -21,7 +21,7 @@ public function it_should_throw_exception_for_missing_type(): void $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Rule configuration must include a "type" field'); - $this->factory->createFromConfig([]); + $this->factory->createFromConfig(config: []); } #[Test] @@ -30,7 +30,7 @@ public function it_should_throw_exception_for_unsupported_type(): void $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Unsupported rule type: unknown'); - $this->factory->createFromConfig(['type' => 'unknown']); + $this->factory->createFromConfig(config: ['type' => 'unknown']); } #[Test] @@ -39,7 +39,7 @@ public function it_should_throw_exception_for_keyword_rule_with_missing_keywords $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Keyword rule must include a "keywords" array'); - $this->factory->createFromConfig(['type' => 'keyword']); + $this->factory->createFromConfig(config: ['type' => 'keyword']); } #[Test] @@ -48,7 +48,7 @@ public function it_should_throw_exception_for_keyword_rule_with_invalid_keywords $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Keyword rule must include a "keywords" array'); - $this->factory->createFromConfig([ + $this->factory->createFromConfig(config: [ 'type' => 'keyword', 'keywords' => 'not-an-array', ]); @@ -57,7 +57,7 @@ public function it_should_throw_exception_for_keyword_rule_with_invalid_keywords #[Test] public function it_should_create_keyword_rule_with_minimal_config(): void { - $rule = $this->factory->createFromConfig([ + $rule = $this->factory->createFromConfig(config: [ 'type' => 'keyword', 'keywords' => ['secret', 'password'], ]); @@ -67,14 +67,14 @@ public function it_should_create_keyword_rule_with_minimal_config(): void // Test the rule works as expected $content = "Line with secret\nNormal line"; - $result = $rule->apply($content); + $result = $rule->apply(content: $content); $this->assertEquals("[REMOVED]\nNormal line", $result); } #[Test] public function it_should_create_keyword_rule_with_full_config(): void { - $rule = $this->factory->createFromConfig([ + $rule = $this->factory->createFromConfig(config: [ 'type' => 'keyword', 'name' => 'custom-keyword-rule', 'keywords' => ['secret', 'password'], @@ -88,7 +88,7 @@ public function it_should_create_keyword_rule_with_full_config(): void // Test the rule works as expected $content = "Line with secret\nLine with SECRET\nNormal line"; - $result = $rule->apply($content); + $result = $rule->apply(content: $content); $this->assertEquals("Line with [REDACTED]\nLine with SECRET\nNormal line", $result); } @@ -98,7 +98,7 @@ public function it_should_throw_exception_for_regex_rule_with_missing_patterns() $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Regex rule must include "patterns" or "usePatterns"'); - $this->factory->createFromConfig(['type' => 'regex']); + $this->factory->createFromConfig(config: ['type' => 'regex']); } #[Test] @@ -107,7 +107,7 @@ public function it_should_throw_exception_for_regex_rule_with_invalid_patterns() $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Regex rule "patterns" object must be an array'); - $this->factory->createFromConfig([ + $this->factory->createFromConfig(config: [ 'type' => 'regex', 'patterns' => 'not-an-array', ]); @@ -116,7 +116,7 @@ public function it_should_throw_exception_for_regex_rule_with_invalid_patterns() #[Test] public function it_should_create_regex_rule_with_custom_patterns(): void { - $rule = $this->factory->createFromConfig([ + $rule = $this->factory->createFromConfig(config: [ 'type' => 'regex', 'name' => 'custom-regex-rule', 'patterns' => [ @@ -129,14 +129,14 @@ public function it_should_create_regex_rule_with_custom_patterns(): void // Test the rule works as expected $content = "Contact us at test@example.com"; - $result = $rule->apply($content); + $result = $rule->apply(content: $content); $this->assertEquals("Contact us at [EMAIL_REMOVED]", $result); } #[Test] public function it_should_create_regex_rule_with_predefined_patterns(): void { - $rule = $this->factory->createFromConfig([ + $rule = $this->factory->createFromConfig(config: [ 'type' => 'regex', 'usePatterns' => ['email', 'ip-address'], ]); @@ -145,14 +145,14 @@ public function it_should_create_regex_rule_with_predefined_patterns(): void // Test the rule works as expected with email pattern $content = "Contact us at test@example.com or visit 192.168.1.1"; - $result = $rule->apply($content); + $result = $rule->apply(content: $content); $this->assertEquals("Contact us at [EMAIL_REMOVED] or visit [IP_ADDRESS_REMOVED]", $result); } #[Test] public function it_should_create_regex_rule_with_mixed_patterns(): void { - $rule = $this->factory->createFromConfig([ + $rule = $this->factory->createFromConfig(config: [ 'type' => 'regex', 'patterns' => [ '/custom-pattern/' => '[CUSTOM_REMOVED]', @@ -164,14 +164,14 @@ public function it_should_create_regex_rule_with_mixed_patterns(): void // Test the rule works with both custom and predefined patterns $content = "Contact us at test@example.com or use custom-pattern"; - $result = $rule->apply($content); + $result = $rule->apply(content: $content); $this->assertEquals("Contact us at [EMAIL_REMOVED] or use [CUSTOM_REMOVED]", $result); } #[Test] public function it_should_create_comment_rule_with_minimal_config(): void { - $rule = $this->factory->createFromConfig([ + $rule = $this->factory->createFromConfig(config: [ 'type' => 'comment', ]); @@ -180,14 +180,14 @@ public function it_should_create_comment_rule_with_minimal_config(): void // Test the rule doesn't modify content with default empty settings $content = "apply($content); + $result = $rule->apply(content: $content); $this->assertEquals($content, $result); } #[Test] public function it_should_create_comment_rule_with_full_config(): void { - $rule = $this->factory->createFromConfig([ + $rule = $this->factory->createFromConfig(config: [ 'type' => 'comment', 'name' => 'custom-comment-rule', 'fileHeaderComment' => 'File header', @@ -202,7 +202,7 @@ public function it_should_create_comment_rule_with_full_config(): void // Test the rule applies comments correctly $content = "apply($content); + $result = $rule->apply(content: $content); $this->assertStringContainsString('// File header', $result); $this->assertStringContainsString('// Class comment', $result); diff --git a/tests/src/Unit/Lib/TokenCounter/CharTokenCounterTest.php b/tests/src/Unit/Lib/TokenCounter/CharTokenCounterTest.php index 0344c090..f9803013 100644 --- a/tests/src/Unit/Lib/TokenCounter/CharTokenCounterTest.php +++ b/tests/src/Unit/Lib/TokenCounter/CharTokenCounterTest.php @@ -19,7 +19,7 @@ public function it_should_return_correct_count_for_empty_file(): void $filePath = $this->fixturesDir . '/empty.txt'; $this->assertFileExists($filePath); - $count = $this->counter->countFile($filePath); + $count = $this->counter->countFile(filePath: $filePath); $this->assertEquals(1, $count); } @@ -29,7 +29,7 @@ public function it_should_return_correct_count_for_simple_file(): void $filePath = $this->fixturesDir . '/simple.txt'; $this->assertFileExists($filePath); - $count = $this->counter->countFile($filePath); + $count = $this->counter->countFile(filePath: $filePath); $this->assertEquals(55, $count); } @@ -39,8 +39,8 @@ public function it_should_handle_multibyte_characters_correctly(): void $filePath = $this->fixturesDir . '/multibyte.txt'; $this->assertFileExists($filePath); - $count = $this->counter->countFile($filePath); - $expectedLength = \mb_strlen(\file_get_contents($filePath)); + $count = $this->counter->countFile(filePath: $filePath); + $expectedLength = \mb_strlen(string: \file_get_contents(filename: $filePath)); $this->assertEquals($expectedLength, $count); } @@ -50,7 +50,7 @@ public function it_should_return_zero_for_non_existent_file(): void $filePath = $this->fixturesDir . '/non-existent-file.txt'; $this->assertFileDoesNotExist($filePath); - $count = $this->counter->countFile($filePath); + $count = $this->counter->countFile(filePath: $filePath); $this->assertEquals(0, $count); } @@ -60,7 +60,7 @@ public function it_should_return_zero_for_directory(): void $dirPath = $this->fixturesDir . '/nested'; $this->assertDirectoryExists($dirPath); - $count = $this->counter->countFile($dirPath); + $count = $this->counter->countFile(filePath: $dirPath); $this->assertEquals(0, $count); } @@ -81,15 +81,15 @@ public function it_should_calculate_directory_count_correctly(): void ], ]; - $count = $this->counter->calculateDirectoryCount($directory); + $count = $this->counter->calculateDirectoryCount(directory: $directory); // Calculate expected count manually $expectedCount = 0; - $expectedCount += \mb_strlen(\file_get_contents($this->fixturesDir . '/simple.txt')); - $expectedCount += \mb_strlen(\file_get_contents($this->fixturesDir . '/multibyte.txt')); - $expectedCount += \mb_strlen(\file_get_contents($this->fixturesDir . '/nested/file1.txt')); - $expectedCount += \mb_strlen(\file_get_contents($this->fixturesDir . '/nested/level1/file2.txt')); - $expectedCount += \mb_strlen(\file_get_contents($this->fixturesDir . '/nested/level1/level2/file3.txt')); + $expectedCount += \mb_strlen(string: \file_get_contents(filename: $this->fixturesDir . '/simple.txt')); + $expectedCount += \mb_strlen(string: \file_get_contents(filename: $this->fixturesDir . '/multibyte.txt')); + $expectedCount += \mb_strlen(string: \file_get_contents(filename: $this->fixturesDir . '/nested/file1.txt')); + $expectedCount += \mb_strlen(string: \file_get_contents(filename: $this->fixturesDir . '/nested/level1/file2.txt')); + $expectedCount += \mb_strlen(string: \file_get_contents(filename: $this->fixturesDir . '/nested/level1/level2/file3.txt')); $this->assertEquals($expectedCount, $count); } @@ -98,7 +98,7 @@ public function it_should_calculate_directory_count_correctly(): void public function it_should_return_zero_for_empty_directory(): void { $directory = []; - $count = $this->counter->calculateDirectoryCount($directory); + $count = $this->counter->calculateDirectoryCount(directory: $directory); $this->assertEquals(0, $count); } @@ -110,7 +110,7 @@ public function it_should_handle_non_existent_files_in_directory(): void 'file2.txt' => $this->fixturesDir . '/non-existent-file2.txt', ]; - $count = $this->counter->calculateDirectoryCount($directory); + $count = $this->counter->calculateDirectoryCount(directory: $directory); $this->assertEquals(0, $count); } @@ -122,8 +122,8 @@ public function it_should_handle_mixed_existent_and_non_existent_files(): void 'file2.txt' => $this->fixturesDir . '/non-existent-file.txt', // Doesn't exist ]; - $count = $this->counter->calculateDirectoryCount($directory); - $expectedCount = \mb_strlen(\file_get_contents($this->fixturesDir . '/simple.txt')); + $count = $this->counter->calculateDirectoryCount(directory: $directory); + $expectedCount = \mb_strlen(string: \file_get_contents(filename: $this->fixturesDir . '/simple.txt')); $this->assertEquals($expectedCount, $count); } diff --git a/tests/src/Unit/Lib/TreeBuilder/DirectorySorterTest.php b/tests/src/Unit/Lib/TreeBuilder/DirectorySorterTest.php index 5cd0ed08..725c289c 100644 --- a/tests/src/Unit/Lib/TreeBuilder/DirectorySorterTest.php +++ b/tests/src/Unit/Lib/TreeBuilder/DirectorySorterTest.php @@ -15,14 +15,14 @@ final class DirectorySorterTest extends TestCase #[Test] public function it_should_sort_empty_array(): void { - $this->assertSame([], DirectorySorter::sort([])); + $this->assertSame([], DirectorySorter::sort(directories: [])); } #[Test] public function it_should_not_sort_single_item_array(): void { $dirs = ['/path/to/dir']; - $this->assertSame($dirs, DirectorySorter::sort($dirs)); + $this->assertSame($dirs, DirectorySorter::sort(directories: $dirs)); } #[Test] @@ -44,7 +44,7 @@ public function it_should_sort_paths_by_depth_then_alphabetically(): void '/c/deep/path', ]; - $this->assertSame($expected, DirectorySorter::sort($dirs)); + $this->assertSame($expected, DirectorySorter::sort(directories: $dirs)); } #[Test] @@ -64,7 +64,7 @@ public function it_should_ensure_parent_directories_come_before_children(): void '/parent/child/grandchild', ]; - $this->assertSame($expected, DirectorySorter::sort($dirs)); + $this->assertSame($expected, DirectorySorter::sort(directories: $dirs)); } #[Test] @@ -82,7 +82,7 @@ public function it_should_normalize_windows_paths_to_unix_style(): void 'parent/child', ]; - $this->assertSame($expected, DirectorySorter::sort($dirs)); + $this->assertSame($expected, DirectorySorter::sort(directories: $dirs)); } #[Test] @@ -100,7 +100,7 @@ public function it_should_remove_windows_drive_letters(): void '/parent/child', ]; - $this->assertSame($expected, DirectorySorter::sort($dirs)); + $this->assertSame($expected, DirectorySorter::sort(directories: $dirs)); } #[Test] @@ -120,13 +120,13 @@ public function it_should_remove_duplicate_paths(): void '/path/two', ]; - $this->assertSame($expected, DirectorySorter::sort($dirs)); + $this->assertSame($expected, DirectorySorter::sort(directories: $dirs)); } #[Test] public function it_should_handle_iterator_input(): void { - $dirs = new \ArrayIterator([ + $dirs = new \ArrayIterator(array: [ '/path/b', '/path/a', ]); @@ -136,7 +136,7 @@ public function it_should_handle_iterator_input(): void '/path/b', ]; - $this->assertSame($expected, DirectorySorter::sort($dirs)); + $this->assertSame($expected, DirectorySorter::sort(directories: $dirs)); } #[Test] @@ -148,7 +148,7 @@ public function it_should_sort_preserving_separators(): void 'windows\\another', ]; - $sorted = DirectorySorter::sortPreservingSeparators($dirs); + $sorted = DirectorySorter::sortPreservingSeparators(directories: $dirs); // We should get another, path, unix/path in alphabetical order $this->assertContains('windows\\another', $sorted); @@ -156,12 +156,12 @@ public function it_should_sort_preserving_separators(): void $this->assertContains('/unix/path', $sorted); // Check that windows\another comes before windows\path - $anotherPos = \array_search('windows\\another', $sorted); - $pathPos = \array_search('windows\\path', $sorted); + $anotherPos = \array_search(needle: 'windows\\another', haystack: $sorted); + $pathPos = \array_search(needle: 'windows\\path', haystack: $sorted); $this->assertLessThan($pathPos, $anotherPos, "windows\\another should come before windows\\path"); // Check that we have the same number of items - $this->assertCount(\count($dirs), $sorted); + $this->assertCount(\count(value: $dirs), $sorted); } #[Test] @@ -173,7 +173,7 @@ public function it_should_preserve_original_drive_letters_when_preserving_separa 'C:\\windows\\another', ]; - $sorted = DirectorySorter::sortPreservingSeparators($dirs); + $sorted = DirectorySorter::sortPreservingSeparators(directories: $dirs); // The original format with drive letters should be preserved foreach ($sorted as $path) { @@ -181,11 +181,11 @@ public function it_should_preserve_original_drive_letters_when_preserving_separa } // All items should be included - $this->assertCount(\count($dirs), $sorted); + $this->assertCount(\count(value: $dirs), $sorted); // Check that C:\windows\another comes before C:\windows\path alphabetically - $anotherPos = \array_search('C:\\windows\\another', $sorted); - $pathPos = \array_search('C:\\windows\\path', $sorted); + $anotherPos = \array_search(needle: 'C:\\windows\\another', haystack: $sorted); + $pathPos = \array_search(needle: 'C:\\windows\\path', haystack: $sorted); if ($anotherPos !== false && $pathPos !== false) { $this->assertLessThan($pathPos, $anotherPos, "C:\\windows\\another should come before C:\\windows\\path"); } @@ -194,7 +194,7 @@ public function it_should_preserve_original_drive_letters_when_preserving_separa #[Test] public function it_should_handle_empty_array_when_preserving_separators(): void { - $this->assertSame([], DirectorySorter::sortPreservingSeparators([])); + $this->assertSame([], DirectorySorter::sortPreservingSeparators(directories: [])); } #[Test] @@ -206,7 +206,7 @@ public function it_should_preserve_original_path_format(): void 'C:\\Users\\user\\Documents', ]; - $sorted = DirectorySorter::sortPreservingSeparators($dirs); + $sorted = DirectorySorter::sortPreservingSeparators(directories: $dirs); // The order might change but the original format should be preserved foreach ($sorted as $path) { @@ -214,7 +214,7 @@ public function it_should_preserve_original_path_format(): void } // Check that we have the same number of items - $this->assertCount(\count($dirs), $sorted); + $this->assertCount(\count(value: $dirs), $sorted); } #[Test] @@ -226,7 +226,7 @@ public function it_should_handle_consistent_path_comparison_with_drive_letters() 'D:\\other\\file.txt', ]; - $sortedPaths = DirectorySorter::sort($dirs); + $sortedPaths = DirectorySorter::sort(directories: $dirs); // Check for correct alphabetical sorting and parent-child relationships $this->assertEquals('/other/file.txt', $sortedPaths[0]); diff --git a/tests/src/Unit/Lib/TreeBuilder/FileTreeBuilderTest.php b/tests/src/Unit/Lib/TreeBuilder/FileTreeBuilderTest.php index f1612393..34a908f7 100644 --- a/tests/src/Unit/Lib/TreeBuilder/FileTreeBuilderTest.php +++ b/tests/src/Unit/Lib/TreeBuilder/FileTreeBuilderTest.php @@ -28,7 +28,7 @@ public function it_should_build_tree_with_default_renderer(): void $this->tempDir . '/dir1/file2.txt', ]; - $result = $builder->buildTree($files, $this->tempDir); + $result = $builder->buildTree(files: $files, basePath: $this->tempDir); // Use the heredoc syntax for clear assertion of the expected tree structure $expectedTree = <<createMockRenderer('custom-tree-output'); - $builder = new FileTreeBuilder($renderer); + $builder = new FileTreeBuilder(renderer: $renderer); $files = [ $this->tempDir . '/file1.txt', $this->tempDir . '/dir1', ]; - $result = $builder->buildTree($files, $this->tempDir); + $result = $builder->buildTree(files: $files, basePath: $this->tempDir); $this->assertSame('custom-tree-output', $result); } @@ -75,14 +75,14 @@ public function it_should_pass_options_to_renderer(): void ) ->willReturn('tree-with-options'); - $builder = new FileTreeBuilder($renderer); + $builder = new FileTreeBuilder(renderer: $renderer); $files = [ $this->tempDir . '/file1.txt', $this->tempDir . '/dir1', ]; - $result = $builder->buildTree($files, $this->tempDir, $options); + $result = $builder->buildTree(files: $files, basePath: $this->tempDir, options: $options); $this->assertSame('tree-with-options', $result); } @@ -91,7 +91,7 @@ public function it_should_pass_options_to_renderer(): void public function it_should_handle_empty_file_list(): void { $builder = new FileTreeBuilder(); - $result = $builder->buildTree([], $this->tempDir); + $result = $builder->buildTree(files: [], basePath: $this->tempDir); // Empty tree should be an empty string $this->assertSame('', $result); @@ -103,15 +103,15 @@ public function it_should_normalize_windows_paths(): void $builder = new FileTreeBuilder(); // Create simple test files in fixed locations for consistent testing - \mkdir($this->tempDir . '/windows/path', 0777, true); - \file_put_contents($this->tempDir . '/windows/path/file.txt', 'content'); + \mkdir(directory: $this->tempDir . '/windows/path', recursive: true); + \file_put_contents(filename: $this->tempDir . '/windows/path/file.txt', data: 'content'); $windowsPaths = [ - \str_replace('/', '\\', $this->tempDir . '/windows/path/file.txt'), - \str_replace('/', '\\', $this->tempDir . '/windows/path'), + \str_replace(search: '/', replace: '\\', subject: $this->tempDir . '/windows/path/file.txt'), + \str_replace(search: '/', replace: '\\', subject: $this->tempDir . '/windows/path'), ]; - $result = $builder->buildTree($windowsPaths, \str_replace('/', '\\', $this->tempDir)); + $result = $builder->buildTree(files: $windowsPaths, basePath: \str_replace(search: '/', replace: '\\', subject: $this->tempDir)); $expectedTree = <<tempDir . '/mixed/unix/path', 0777, true); - \mkdir($this->tempDir . '/mixed/windows/path', 0777, true); - \file_put_contents($this->tempDir . '/mixed/unix/path/unix-file.txt', 'content'); - \file_put_contents($this->tempDir . '/mixed/windows/path/windows-file.txt', 'content'); + \mkdir(directory: $this->tempDir . '/mixed/unix/path', recursive: true); + \mkdir(directory: $this->tempDir . '/mixed/windows/path', recursive: true); + \file_put_contents(filename: $this->tempDir . '/mixed/unix/path/unix-file.txt', data: 'content'); + \file_put_contents(filename: $this->tempDir . '/mixed/windows/path/windows-file.txt', data: 'content'); // Create a mix of Windows and Unix paths $mixedPaths = [ $this->tempDir . '/mixed/unix/path/unix-file.txt', - \str_replace('/', '\\', $this->tempDir . '/mixed/windows/path/windows-file.txt'), + \str_replace(search: '/', replace: '\\', subject: $this->tempDir . '/mixed/windows/path/windows-file.txt'), $this->tempDir . '/mixed/unix/path', - \str_replace('/', '\\', $this->tempDir . '/mixed/windows/path'), + \str_replace(search: '/', replace: '\\', subject: $this->tempDir . '/mixed/windows/path'), ]; - $result = $builder->buildTree($mixedPaths, $this->tempDir); + $result = $builder->buildTree(files: $mixedPaths, basePath: $this->tempDir); $expectedTree = <<tempDir . '/file1.txt', // File ]; - $result = $builder->buildTree($files, $this->tempDir); + $result = $builder->buildTree(files: $files, basePath: $this->tempDir); $expectedTree = <<tempDir . '/dir1', ]; - $result = $builder->buildTree($files, $this->tempDir); + $result = $builder->buildTree(files: $files, basePath: $this->tempDir); $expectedTree = <<tempDir . '/dir2/subdir/file4.txt', ]; - $result = $builder->buildTree($files, $basePath); + $result = $builder->buildTree(files: $files, basePath: $basePath); $expectedTree = <<buildTree($files, $this->tempDir, ['includeFiles' => false]); + $result = $builder->buildTree(files: $files, basePath: $this->tempDir, options: ['includeFiles' => false]); $expectedTree = <<fixturesDir = \dirname(__DIR__, 3) . '/fixtures/TreeBuilder'; + $this->fixturesDir = \dirname(path: __DIR__, levels: 3) . '/fixtures/TreeBuilder'; // Create fixtures directory if it doesn't exist - if (!\is_dir($this->fixturesDir)) { - \mkdir($this->fixturesDir, 0777, true); + if (!\is_dir(filename: $this->fixturesDir)) { + \mkdir(directory: $this->fixturesDir, recursive: true); } // Create temp directory for file operations $this->tempDir = \sys_get_temp_dir() . '/test-tree-builder-' . \uniqid(); - \mkdir($this->tempDir, 0777, true); + \mkdir(directory: $this->tempDir, recursive: true); // Create some test files and directories - \mkdir($this->tempDir . '/dir1', 0777, true); - \mkdir($this->tempDir . '/dir2/subdir', 0777, true); - \file_put_contents($this->tempDir . '/file1.txt', 'content'); - \file_put_contents($this->tempDir . '/dir1/file2.txt', 'content'); - \file_put_contents($this->tempDir . '/dir2/file3.txt', 'content'); - \file_put_contents($this->tempDir . '/dir2/subdir/file4.txt', 'content'); + \mkdir(directory: $this->tempDir . '/dir1', recursive: true); + \mkdir(directory: $this->tempDir . '/dir2/subdir', recursive: true); + \file_put_contents(filename: $this->tempDir . '/file1.txt', data: 'content'); + \file_put_contents(filename: $this->tempDir . '/dir1/file2.txt', data: 'content'); + \file_put_contents(filename: $this->tempDir . '/dir2/file3.txt', data: 'content'); + \file_put_contents(filename: $this->tempDir . '/dir2/subdir/file4.txt', data: 'content'); } protected function tearDown(): void @@ -268,23 +268,23 @@ protected function tearDown(): void private function removeDirectory(string $dir): void { - if (!\is_dir($dir)) { + if (!\is_dir(filename: $dir)) { return; } - $files = \array_diff(\scandir($dir), ['.', '..']); + $files = \array_diff(\scandir(directory: $dir), ['.', '..']); foreach ($files as $file) { $path = "$dir/$file"; - if (\is_dir($path)) { + if (\is_dir(filename: $path)) { $this->removeDirectory($path); } else { - \unlink($path); + \unlink(filename: $path); } } - \rmdir($dir); + \rmdir(directory: $dir); } /** diff --git a/tests/src/Unit/Lib/Variable/Provider/CompositeVariableProviderTest.php b/tests/src/Unit/Lib/Variable/Provider/CompositeVariableProviderTest.php index db98a5ac..ed7c23d7 100644 --- a/tests/src/Unit/Lib/Variable/Provider/CompositeVariableProviderTest.php +++ b/tests/src/Unit/Lib/Variable/Provider/CompositeVariableProviderTest.php @@ -18,8 +18,8 @@ public function it_should_return_false_when_no_providers_added(): void { $provider = new CompositeVariableProvider(); - $this->assertFalse($provider->has('TEST_VAR')); - $this->assertNull($provider->get('TEST_VAR')); + $this->assertFalse($provider->has(name: 'TEST_VAR')); + $this->assertNull($provider->get(name: 'TEST_VAR')); } #[Test] @@ -38,7 +38,7 @@ public function it_should_check_all_providers_until_one_returns_true(): void $composite = new CompositeVariableProvider($provider1, $provider2, $provider3); - $this->assertTrue($composite->has('TEST_VAR')); + $this->assertTrue($composite->has(name: 'TEST_VAR')); } #[Test] @@ -60,7 +60,7 @@ public function it_should_return_value_from_first_provider_that_has_variable(): $composite = new CompositeVariableProvider($provider1, $provider2, $provider3); - $this->assertSame('test_value', $composite->get('TEST_VAR')); + $this->assertSame('test_value', $composite->get(name: 'TEST_VAR')); } #[Test] @@ -79,10 +79,10 @@ public function it_should_respect_provider_priority(): void $composite = new CompositeVariableProvider($lowPriority); // Add high priority provider - $composite->addProviderWithHighPriority($highPriority); + $composite->addProviderWithHighPriority(provider: $highPriority); // The high priority provider should be checked first - $this->assertSame('high_priority_value', $composite->get('SHARED_VAR')); + $this->assertSame('high_priority_value', $composite->get(name: 'SHARED_VAR')); } #[Test] @@ -93,8 +93,8 @@ public function it_should_add_providers_correctly(): void $provider3 = $this->createMock(VariableProviderInterface::class); $composite = new CompositeVariableProvider($provider1); - $composite->addProvider($provider2); - $composite->addProviderWithHighPriority($provider3); + $composite->addProvider(provider: $provider2); + $composite->addProviderWithHighPriority(provider: $provider3); $providers = $composite->getProviders(); diff --git a/tests/src/Unit/Lib/Variable/Provider/DotEnvVariableProviderTest.php b/tests/src/Unit/Lib/Variable/Provider/DotEnvVariableProviderTest.php index 0168969f..a539878b 100644 --- a/tests/src/Unit/Lib/Variable/Provider/DotEnvVariableProviderTest.php +++ b/tests/src/Unit/Lib/Variable/Provider/DotEnvVariableProviderTest.php @@ -24,9 +24,9 @@ public function it_should_check_repository_for_variable_existence(): void ->with('TEST_VAR') ->willReturn(true); - $provider = new DotEnvVariableProvider($this->repository); + $provider = new DotEnvVariableProvider(repository: $this->repository); - $this->assertTrue($provider->has('TEST_VAR')); + $this->assertTrue($provider->has(name: 'TEST_VAR')); } #[Test] @@ -43,9 +43,9 @@ public function it_should_get_variable_from_repository(): void ->with('TEST_VAR') ->willReturn('test_value'); - $provider = new DotEnvVariableProvider($this->repository); + $provider = new DotEnvVariableProvider(repository: $this->repository); - $this->assertSame('test_value', $provider->get('TEST_VAR')); + $this->assertSame('test_value', $provider->get(name: 'TEST_VAR')); } #[Test] @@ -62,10 +62,10 @@ public function it_should_return_null_for_missing_variable(): void ->with('MISSING_VAR') ->willReturn(null); - $provider = new DotEnvVariableProvider($this->repository); + $provider = new DotEnvVariableProvider(repository: $this->repository); - $this->assertFalse($provider->has('MISSING_VAR')); - $this->assertNull($provider->get('MISSING_VAR')); + $this->assertFalse($provider->has(name: 'MISSING_VAR')); + $this->assertNull($provider->get(name: 'MISSING_VAR')); } #[Test] @@ -74,7 +74,7 @@ public function it_should_load_env_file_when_path_provided(): void // Create temporary .env file in system temp directory $tempDir = \sys_get_temp_dir(); $envPath = $tempDir . '/.env.test'; - \file_put_contents($envPath, "TEST_ENV_VAR=from_env_file\n"); + \file_put_contents(filename: $envPath, data: "TEST_ENV_VAR=from_env_file\n"); // We need to use a real repository for this test // This requires us to have phpdotenv package installed @@ -93,13 +93,13 @@ public function it_should_load_env_file_when_path_provided(): void try { // This might fail in test environment without dotenv properly set up // But we're just testing that the constructor uses the rootPath - new DotEnvVariableProvider($repository, $tempDir, '.env.test'); + new DotEnvVariableProvider(repository: $repository, rootPath: $tempDir, envFileName: '.env.test'); // If it didn't throw, we consider it a success for this test $this->addToAssertionCount(1); } finally { // Clean up temp file - if (\file_exists($envPath)) { - \unlink($envPath); + if (\file_exists(filename: $envPath)) { + \unlink(filename: $envPath); } } } diff --git a/tests/src/Unit/Lib/Variable/Provider/PredefinedVariableProviderTest.php b/tests/src/Unit/Lib/Variable/Provider/PredefinedVariableProviderTest.php index 1e27fb5b..32864cc5 100644 --- a/tests/src/Unit/Lib/Variable/Provider/PredefinedVariableProviderTest.php +++ b/tests/src/Unit/Lib/Variable/Provider/PredefinedVariableProviderTest.php @@ -18,29 +18,29 @@ class PredefinedVariableProviderTest extends TestCase public function it_should_have_predefined_variables(): void { // Test some key variables that should be predefined - $this->assertTrue($this->provider->has('DATETIME')); - $this->assertTrue($this->provider->has('DATE')); - $this->assertTrue($this->provider->has('TIME')); - $this->assertTrue($this->provider->has('TIMESTAMP')); - $this->assertTrue($this->provider->has('USER')); - $this->assertTrue($this->provider->has('HOME_DIR')); - $this->assertTrue($this->provider->has('TEMP_DIR')); - $this->assertTrue($this->provider->has('OS')); - $this->assertTrue($this->provider->has('HOSTNAME')); - $this->assertTrue($this->provider->has('PWD')); + $this->assertTrue($this->provider->has(name: 'DATETIME')); + $this->assertTrue($this->provider->has(name: 'DATE')); + $this->assertTrue($this->provider->has(name: 'TIME')); + $this->assertTrue($this->provider->has(name: 'TIMESTAMP')); + $this->assertTrue($this->provider->has(name: 'USER')); + $this->assertTrue($this->provider->has(name: 'HOME_DIR')); + $this->assertTrue($this->provider->has(name: 'TEMP_DIR')); + $this->assertTrue($this->provider->has(name: 'OS')); + $this->assertTrue($this->provider->has(name: 'HOSTNAME')); + $this->assertTrue($this->provider->has(name: 'PWD')); } #[Test] public function it_should_not_have_arbitrary_variables(): void { - $this->assertFalse($this->provider->has('NON_EXISTENT_VARIABLE')); - $this->assertNull($this->provider->get('NON_EXISTENT_VARIABLE')); + $this->assertFalse($this->provider->has(name: 'NON_EXISTENT_VARIABLE')); + $this->assertNull($this->provider->get(name: 'NON_EXISTENT_VARIABLE')); } #[Test] public function it_should_return_timestamp_as_string(): void { - $timestamp = $this->provider->get('TIMESTAMP'); + $timestamp = $this->provider->get(name: 'TIMESTAMP'); $this->assertIsString($timestamp); // Timestamp should be a numeric string @@ -52,19 +52,19 @@ public function it_should_return_timestamp_as_string(): void #[Test] public function it_should_return_date_in_correct_format(): void { - $date = $this->provider->get('DATE'); + $date = $this->provider->get(name: 'DATE'); $this->assertIsString($date); // Validate date format: Y-m-d $this->assertMatchesRegularExpression('/^\d{4}-\d{2}-\d{2}$/', $date); // Should match current date - $this->assertSame(\date('Y-m-d'), $date); + $this->assertSame(\date(format: 'Y-m-d'), $date); } #[Test] public function it_should_return_current_working_directory(): void { - $pwd = $this->provider->get('PWD'); + $pwd = $this->provider->get(name: 'PWD'); $this->assertIsString($pwd); // Should match current working directory or '.' if unavailable @@ -75,7 +75,7 @@ public function it_should_return_current_working_directory(): void #[Test] public function it_should_return_temp_directory(): void { - $tempDir = $this->provider->get('TEMP_DIR'); + $tempDir = $this->provider->get(name: 'TEMP_DIR'); $this->assertIsString($tempDir); $this->assertSame(\sys_get_temp_dir(), $tempDir); diff --git a/tests/src/Unit/Lib/Variable/VariableReplacementProcessorTest.php b/tests/src/Unit/Lib/Variable/VariableReplacementProcessorTest.php index 9fbff69c..175eca0c 100644 --- a/tests/src/Unit/Lib/Variable/VariableReplacementProcessorTest.php +++ b/tests/src/Unit/Lib/Variable/VariableReplacementProcessorTest.php @@ -33,10 +33,10 @@ public static function variableSyntaxProvider(): array #[Test] public function it_should_not_modify_text_without_variables(): void { - $processor = new VariableReplacementProcessor($this->provider); + $processor = new VariableReplacementProcessor(provider: $this->provider); $text = 'This is a simple text without variables'; - $this->assertSame($text, $processor->process($text)); + $this->assertSame($text, $processor->process(text: $text)); } #[Test] @@ -46,11 +46,11 @@ public function it_should_replace_dollar_brace_syntax_variables(): void $this->provider->method('has')->with('VAR_NAME')->willReturn(true); $this->provider->method('get')->with('VAR_NAME')->willReturn('replacement_value'); - $processor = new VariableReplacementProcessor($this->provider); + $processor = new VariableReplacementProcessor(provider: $this->provider); $text = 'This text has a ${VAR_NAME} variable'; $expected = 'This text has a replacement_value variable'; - $this->assertSame($expected, $processor->process($text)); + $this->assertSame($expected, $processor->process(text: $text)); } #[Test] @@ -60,11 +60,11 @@ public function it_should_replace_double_brace_syntax_variables(): void $this->provider->method('has')->with('VAR_NAME')->willReturn(true); $this->provider->method('get')->with('VAR_NAME')->willReturn('replacement_value'); - $processor = new VariableReplacementProcessor($this->provider); + $processor = new VariableReplacementProcessor(provider: $this->provider); $text = 'This text has a {{VAR_NAME}} variable'; $expected = 'This text has a replacement_value variable'; - $this->assertSame($expected, $processor->process($text)); + $this->assertSame($expected, $processor->process(text: $text)); } #[Test] @@ -81,11 +81,11 @@ public function it_should_replace_multiple_variables(): void ['SECOND', 'second_value'], ]); - $processor = new VariableReplacementProcessor($this->provider); + $processor = new VariableReplacementProcessor(provider: $this->provider); $text = 'First: ${FIRST}, Second: {{SECOND}}'; $expected = 'First: first_value, Second: second_value'; - $this->assertSame($expected, $processor->process($text)); + $this->assertSame($expected, $processor->process(text: $text)); } #[Test] @@ -94,11 +94,11 @@ public function it_should_keep_unknown_variables_with_original_syntax(): void // Setup provider mock to return false for all has() calls $this->provider->method('has')->willReturn(false); - $processor = new VariableReplacementProcessor($this->provider); + $processor = new VariableReplacementProcessor(provider: $this->provider); $text = 'Unknown var: ${UNKNOWN_VAR}'; // Should keep the original syntax - $this->assertSame($text, $processor->process($text)); + $this->assertSame($text, $processor->process(text: $text)); } #[Test] @@ -108,11 +108,11 @@ public function it_should_handle_empty_replacement(): void $this->provider->method('has')->with('EMPTY_VAR')->willReturn(true); $this->provider->method('get')->with('EMPTY_VAR')->willReturn(''); - $processor = new VariableReplacementProcessor($this->provider); + $processor = new VariableReplacementProcessor(provider: $this->provider); $text = 'Empty var: ${EMPTY_VAR}'; $expected = 'Empty var: '; - $this->assertSame($expected, $processor->process($text)); + $this->assertSame($expected, $processor->process(text: $text)); } #[Test] @@ -122,11 +122,11 @@ public function it_should_handle_null_replacement_as_empty_string(): void $this->provider->method('has')->with('NULL_VAR')->willReturn(true); $this->provider->method('get')->with('NULL_VAR')->willReturn(null); - $processor = new VariableReplacementProcessor($this->provider); + $processor = new VariableReplacementProcessor(provider: $this->provider); $text = 'Null var: ${NULL_VAR}'; $expected = 'Null var: '; - $this->assertSame($expected, $processor->process($text)); + $this->assertSame($expected, $processor->process(text: $text)); } #[Test] @@ -145,10 +145,10 @@ public function it_should_log_replacements_when_logger_provided(): void ['name' => 'TEST_VAR', 'value' => 'test_value'], ); - $processor = new VariableReplacementProcessor($this->provider, $this->logger); + $processor = new VariableReplacementProcessor(provider: $this->provider, logger: $this->logger); $text = 'Test var: ${TEST_VAR}'; - $processor->process($text); + $processor->process(text: $text); } #[Test] @@ -159,11 +159,11 @@ public function it_should_handle_various_variable_syntax(string $varSyntax, stri $this->provider->method('has')->with($name)->willReturn(true); $this->provider->method('get')->with($name)->willReturn('it_works'); - $processor = new VariableReplacementProcessor($this->provider); + $processor = new VariableReplacementProcessor(provider: $this->provider); $text = "Testing {$varSyntax}"; $expected = 'Testing it_works'; - $this->assertSame($expected, $processor->process($text)); + $this->assertSame($expected, $processor->process(text: $text)); } protected function setUp(): void diff --git a/tests/src/Unit/Lib/Variable/VariableResolverTest.php b/tests/src/Unit/Lib/Variable/VariableResolverTest.php index 595a4237..3a0a7065 100644 --- a/tests/src/Unit/Lib/Variable/VariableResolverTest.php +++ b/tests/src/Unit/Lib/Variable/VariableResolverTest.php @@ -19,11 +19,11 @@ public function it_should_return_null_for_null_input(): void { // Create a custom processor to use instead of a mock $customProcessor = new VariableReplacementProcessor( - $this->createCustomProvider(), + provider: $this->createCustomProvider(), ); - $resolver = new VariableResolver($customProcessor); - $this->assertNull($resolver->resolve(null)); + $resolver = new VariableResolver(processor: $customProcessor); + $this->assertNull($resolver->resolve()); } #[Test] @@ -35,10 +35,10 @@ public function it_should_process_string_input(): void 'VAR' => 'processed string', ]); - $processor = new VariableReplacementProcessor($provider); - $resolver = new VariableResolver($processor); + $processor = new VariableReplacementProcessor(provider: $provider); + $resolver = new VariableResolver(processor: $processor); - $result = $resolver->resolve('${VAR}'); + $result = $resolver->resolve(strings: '${VAR}'); $this->assertSame('processed string', $result); } @@ -52,8 +52,8 @@ public function it_should_process_each_string_in_array_input(): void 'OTHER_VAR' => 'also processed', ]); - $processor = new VariableReplacementProcessor($provider); - $resolver = new VariableResolver($processor); + $processor = new VariableReplacementProcessor(provider: $provider); + $resolver = new VariableResolver(processor: $processor); $input = [ 'first ${VAR}', @@ -67,7 +67,7 @@ public function it_should_process_each_string_in_array_input(): void 'third also processed', ]; - $this->assertSame($expected, $resolver->resolve($input)); + $this->assertSame($expected, $resolver->resolve(strings: $input)); } #[Test] @@ -78,8 +78,8 @@ public function it_should_handle_nested_arrays(): void 'VAR' => 'processed', ]); - $processor = new VariableReplacementProcessor($provider); - $resolver = new VariableResolver($processor); + $processor = new VariableReplacementProcessor(provider: $provider); + $resolver = new VariableResolver(processor: $processor); $input = [ 'outer ${VAR}', @@ -97,27 +97,27 @@ public function it_should_handle_nested_arrays(): void ], ]; - $this->assertSame($expected, $resolver->resolve($input)); + $this->assertSame($expected, $resolver->resolve(strings: $input)); } #[Test] public function it_should_handle_empty_string(): void { $provider = $this->createCustomProvider(); - $processor = new VariableReplacementProcessor($provider); - $resolver = new VariableResolver($processor); + $processor = new VariableReplacementProcessor(provider: $provider); + $resolver = new VariableResolver(processor: $processor); - $this->assertSame('', $resolver->resolve('')); + $this->assertSame('', $resolver->resolve(strings: '')); } #[Test] public function it_should_handle_empty_array(): void { $provider = $this->createCustomProvider(); - $processor = new VariableReplacementProcessor($provider); - $resolver = new VariableResolver($processor); + $processor = new VariableReplacementProcessor(provider: $provider); + $resolver = new VariableResolver(processor: $processor); - $this->assertSame([], $resolver->resolve([])); + $this->assertSame([], $resolver->resolve(strings: [])); } #[Test] @@ -136,8 +136,8 @@ public function get(string $name): ?string } }; - $processor = new VariableReplacementProcessor($provider); - $resolver = new VariableResolver($processor); + $processor = new VariableReplacementProcessor(provider: $provider); + $resolver = new VariableResolver(processor: $processor); $input = [ '${PREFIX}first', @@ -151,7 +151,7 @@ public function get(string $name): ?string 'processed:third', ]; - $this->assertSame($expected, $resolver->resolve($input)); + $this->assertSame($expected, $resolver->resolve(strings: $input)); } /** diff --git a/tests/src/Unit/Lib/Variable/VariableSystemEdgeCasesTest.php b/tests/src/Unit/Lib/Variable/VariableSystemEdgeCasesTest.php index bbaa38c2..eef82108 100644 --- a/tests/src/Unit/Lib/Variable/VariableSystemEdgeCasesTest.php +++ b/tests/src/Unit/Lib/Variable/VariableSystemEdgeCasesTest.php @@ -53,22 +53,22 @@ public function get(string $name): ?string } }; - $processor = new VariableReplacementProcessor($nestedProvider); - $resolver = new VariableResolver($processor); + $processor = new VariableReplacementProcessor(provider: $nestedProvider); + $resolver = new VariableResolver(processor: $processor); // Test case for nested variables - these are not automatically resolved recursively // since the processor doesn't recursively process - $result = $resolver->resolve('${LEVEL3}'); + $result = $resolver->resolve(strings: '${LEVEL3}'); // Should only resolve one level: "${LEVEL3}" -> "references ${LEVEL2}" $this->assertSame('references ${LEVEL2}', $result); // If we process it a second time, we get one level deeper - $result = $resolver->resolve($result); + $result = $resolver->resolve(strings: $result); $this->assertSame('references uses ${LEVEL1}', $result); // And once more to fully resolve - $result = $resolver->resolve($result); + $result = $resolver->resolve(strings: $result); $this->assertSame('references uses value1', $result); } @@ -93,15 +93,15 @@ public function get(string $name): ?string } }; - $processor = new VariableReplacementProcessor($circularProvider); - $resolver = new VariableResolver($processor); + $processor = new VariableReplacementProcessor(provider: $circularProvider); + $resolver = new VariableResolver(processor: $processor); // With circular references, each resolution replaces one level - $result = $resolver->resolve('${CIRCULAR1}'); + $result = $resolver->resolve(strings: '${CIRCULAR1}'); $this->assertSame('${CIRCULAR2}', $result); // Second level replaces to the other circular var - $result = $resolver->resolve($result); + $result = $resolver->resolve(strings: $result); $this->assertSame('${CIRCULAR1}', $result); // You could potentially get in an infinite loop if you keep reprocessing, @@ -130,10 +130,10 @@ public function get(string $name): ?string } }; - $processor = new VariableReplacementProcessor($specialCharsProvider); - $resolver = new VariableResolver($processor); + $processor = new VariableReplacementProcessor(provider: $specialCharsProvider); + $resolver = new VariableResolver(processor: $processor); - $result = $resolver->resolve('Value: ${SPECIAL}'); + $result = $resolver->resolve(strings: 'Value: ${SPECIAL}'); $expected = 'Value: ' . $value; $this->assertSame($expected, $result); @@ -160,15 +160,15 @@ public function get(string $name): ?string } }; - $processor = new VariableReplacementProcessor($provider); - $resolver = new VariableResolver($processor); + $processor = new VariableReplacementProcessor(provider: $provider); + $resolver = new VariableResolver(processor: $processor); // Test adjacent variables - $result = $resolver->resolve('${FIRST}${SECOND}${THIRD}'); + $result = $resolver->resolve(strings: '${FIRST}${SECOND}${THIRD}'); $this->assertSame('firstsecondthird', $result); // Test mixed syntax adjacent variables - $result = $resolver->resolve('${FIRST}{{SECOND}}${THIRD}'); + $result = $resolver->resolve(strings: '${FIRST}{{SECOND}}${THIRD}'); $this->assertSame('firstsecondthird', $result); } @@ -191,8 +191,8 @@ public function get(string $name): ?string } }; - $processor = new VariableReplacementProcessor($provider); - $resolver = new VariableResolver($processor); + $processor = new VariableReplacementProcessor(provider: $provider); + $resolver = new VariableResolver(processor: $processor); // Test various malformed variable patterns $testCases = [ @@ -216,7 +216,7 @@ public function get(string $name): ?string ]; foreach ($testCases as $input => $expected) { - $result = $resolver->resolve($input); + $result = $resolver->resolve(strings: $input); $this->assertSame($expected, $result, "Failed for input: $input"); } } diff --git a/tests/src/Unit/Lib/Variable/VariableSystemIntegrationTest.php b/tests/src/Unit/Lib/Variable/VariableSystemIntegrationTest.php index ede91a4e..589daa2e 100644 --- a/tests/src/Unit/Lib/Variable/VariableSystemIntegrationTest.php +++ b/tests/src/Unit/Lib/Variable/VariableSystemIntegrationTest.php @@ -23,7 +23,7 @@ public function it_should_resolve_variables_in_simple_string(): void $input = 'Project: ${PROJECT_NAME}, Version: ${VERSION}'; $expected = 'Project: context-generator, Version: 1.0.0'; - $result = $this->resolver->resolve($input); + $result = $this->resolver->resolve(strings: $input); $this->assertSame($expected, $result); } @@ -34,7 +34,7 @@ public function it_should_resolve_variables_with_different_syntax(): void $input = 'Project: ${PROJECT_NAME}, Version: {{VERSION}}'; $expected = 'Project: context-generator, Version: 1.0.0'; - $result = $this->resolver->resolve($input); + $result = $this->resolver->resolve(strings: $input); $this->assertSame($expected, $result); } @@ -44,10 +44,10 @@ public function it_should_resolve_system_variables(): void { $input = 'Current date: ${DATE}, OS: ${OS}'; - $result = $this->resolver->resolve($input); + $result = $this->resolver->resolve(strings: $input); // Verify system variables were replaced - $this->assertStringContainsString('Current date: ' . \date('Y-m-d'), $result); + $this->assertStringContainsString('Current date: ' . \date(format: 'Y-m-d'), $result); $this->assertStringContainsString('OS: ' . PHP_OS, $result); } @@ -65,11 +65,11 @@ public function it_should_resolve_variables_in_array(): void ], ]; - $result = $this->resolver->resolve($input); + $result = $this->resolver->resolve(strings: $input); $this->assertSame('context-generator', $result['project']); $this->assertSame('1.0.0', $result['version']); - $this->assertSame(\date('Y-m-d'), $result['date']); + $this->assertSame(\date(format: 'Y-m-d'), $result['date']); $this->assertSame('test_value', $result['nested']['test']); $this->assertSame('', $result['nested']['emptyVar']); $this->assertSame('${UNKNOWN_VAR}', $result['nested']['unknownVar']); @@ -101,10 +101,10 @@ public function get(string $name): ?string new PredefinedVariableProvider(), // Lowest priority ); - $processor = new VariableReplacementProcessor($compositeProvider); - $resolver = new VariableResolver($processor); + $processor = new VariableReplacementProcessor(provider: $compositeProvider); + $resolver = new VariableResolver(processor: $processor); - $result = $resolver->resolve('Date: ${DATE}'); + $result = $resolver->resolve(strings: 'Date: ${DATE}'); // Should use our custom DATE value, not the system one $this->assertSame('Date: CUSTOM_DATE_VALUE', $result); @@ -116,7 +116,7 @@ public function it_should_leave_unknown_variables_untouched(): void $input = 'Unknown: ${DOES_NOT_EXIST}, Known: ${TEST_VAR}'; $expected = 'Unknown: ${DOES_NOT_EXIST}, Known: test_value'; - $result = $this->resolver->resolve($input); + $result = $this->resolver->resolve(strings: $input); $this->assertSame($expected, $result); } @@ -126,25 +126,25 @@ public function it_should_handle_complex_text_with_multiple_variables(): void { $input = <<<'TEXT' # ${PROJECT_NAME} v${VERSION} - + Current date: ${DATE} Environment: ${OS} - + ## Configuration - + - Test variable: ${TEST_VAR} - Non-existent: ${NON_EXISTENT} - Using double braces: {{PROJECT_NAME}} - + ## Contact - + User: ${USER} TEXT; - $result = $this->resolver->resolve($input); + $result = $this->resolver->resolve(strings: $input); // Check that all variables were properly replaced - $this->assertStringContainsString('Current date: ' . \date('Y-m-d'), $result); + $this->assertStringContainsString('Current date: ' . \date(format: 'Y-m-d'), $result); $this->assertStringContainsString('Environment: ' . PHP_OS, $result); $this->assertStringContainsString('Test variable: test_value', $result); $this->assertStringContainsString('Non-existent: ${NON_EXISTENT}', $result); @@ -185,9 +185,9 @@ public function get(string $name): ?string ); // Create processor with composite provider - $processor = new VariableReplacementProcessor($compositeProvider); + $processor = new VariableReplacementProcessor(provider: $compositeProvider); // Create resolver with processor - $this->resolver = new VariableResolver($processor); + $this->resolver = new VariableResolver(processor: $processor); } } diff --git a/tests/src/Unit/Source/BaseSourceConstructorTest.php b/tests/src/Unit/Source/BaseSourceConstructorTest.php index 6afc0d36..485e6b7d 100644 --- a/tests/src/Unit/Source/BaseSourceConstructorTest.php +++ b/tests/src/Unit/Source/BaseSourceConstructorTest.php @@ -48,7 +48,7 @@ public function it_should_parse_content_using_parser(): void ->with($source) ->willReturn('Parsed content'); - $this->assertEquals('Parsed content', $source->parseContent($parser, new ModifiersApplier([]))); + $this->assertEquals('Parsed content', $source->parseContent(parser: $parser, modifiersApplier: new ModifiersApplier(modifiers: []))); } /** diff --git a/tests/src/Unit/Source/FileSourceConstructorTest.php b/tests/src/Unit/Source/FileSourceConstructorTest.php index 0df4a211..cb77a292 100644 --- a/tests/src/Unit/Source/FileSourceConstructorTest.php +++ b/tests/src/Unit/Source/FileSourceConstructorTest.php @@ -38,7 +38,7 @@ public function it_should_store_constructor_parameters(): void size: $size, date: $date, ignoreUnreadableDirs: $ignoreUnreadableDirs, - treeView: new TreeViewConfig($showTreeView), + treeView: new TreeViewConfig(enabled: $showTreeView), modifiers: $modifiers, ); diff --git a/tests/src/Unit/Source/FileSourceFromArrayTest.php b/tests/src/Unit/Source/FileSourceFromArrayTest.php index 9202416b..3522a01e 100644 --- a/tests/src/Unit/Source/FileSourceFromArrayTest.php +++ b/tests/src/Unit/Source/FileSourceFromArrayTest.php @@ -21,7 +21,7 @@ public function it_should_create_from_array_with_minimal_parameters(): void 'sourcePaths' => 'path/to/file.php', ]; - $source = $this->factory->create($data); + $source = $this->factory->create(config: $data); $this->assertEquals(['/test/path/to/file.php'], $source->sourcePaths); $this->assertEquals('', $source->getDescription()); @@ -48,7 +48,7 @@ public function it_should_create_from_array_with_all_parameters(): void 'modifiers' => ['modifier1', 'modifier2'], ]; - $source = $this->factory->create($data); + $source = $this->factory->create(config: $data); $expectedPaths = ['/test/path/to/file.php', '/test/path/to/directory']; $this->assertEquals($expectedPaths, $source->sourcePaths); @@ -72,7 +72,7 @@ public function it_should_support_array_file_pattern(): void 'filePattern' => ['*.php', '*.js'], ]; - $source = $this->factory->create($data); + $source = $this->factory->create(config: $data); $this->assertEquals($data['filePattern'], $source->filePattern); } @@ -85,7 +85,7 @@ public function it_should_support_excludePatterns_as_alias_for_notPath(): void 'excludePatterns' => ['vendor', 'node_modules'], ]; - $source = $this->factory->create($data); + $source = $this->factory->create(config: $data); $this->assertEquals($data['excludePatterns'], $source->notPath); } @@ -99,7 +99,7 @@ public function it_should_prepend_root_path_to_source_paths(): void $rootPath = '/var/www'; - $source = (new FileSourceFactory($this->createDirectories($rootPath)))->create($data); + $source = (new FileSourceFactory(dirs: $this->createDirectories($rootPath)))->create(config: $data); $expectedPaths = [ '/var/www/path/to/file.php', @@ -115,7 +115,7 @@ public function it_should_throw_exception_if_sourcePaths_is_missing(): void $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('File source must have a "sourcePaths" property'); - $this->factory->create([]); + $this->factory->create(config: []); } #[Test] @@ -124,7 +124,7 @@ public function it_should_throw_exception_if_sourcePaths_is_not_string_or_array( $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('"sourcePaths" must be a string or array in source'); - $this->factory->create(['sourcePaths' => 123]); + $this->factory->create(config: ['sourcePaths' => 123]); } #[Test] @@ -133,7 +133,7 @@ public function it_should_throw_exception_if_filePattern_is_not_string_or_array( $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('filePattern must be a string or an array of strings'); - $this->factory->create([ + $this->factory->create(config: [ 'sourcePaths' => 'path/to/file.php', 'filePattern' => 123, ]); @@ -145,7 +145,7 @@ public function it_should_throw_exception_if_filePattern_array_contains_non_stri $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('All elements in filePattern must be strings'); - $this->factory->create([ + $this->factory->create(config: [ 'sourcePaths' => 'path/to/file.php', 'filePattern' => ['*.php', 123], ]); @@ -165,7 +165,7 @@ public function it_should_serialize_to_json(): void size: ['> 10K', '< 1M'], date: ['since yesterday'], ignoreUnreadableDirs: true, - treeView: new TreeViewConfig(false), + treeView: new TreeViewConfig(enabled: false), modifiers: ['modifier1', 'modifier2'], ); @@ -190,7 +190,7 @@ public function it_should_serialize_to_json(): void 'modifiers' => ['modifier1', 'modifier2'], ]; - $this->assertEquals($expected, \json_decode(\json_encode($source->jsonSerialize()), true)); + $this->assertEquals($expected, \json_decode(json: \json_encode(value: $source->jsonSerialize()), associative: true)); } #[Test] @@ -214,13 +214,13 @@ public function it_should_omit_empty_values_in_json_serialization(): void ], ]; - $this->assertEquals($expected, \json_decode(\json_encode($source->jsonSerialize()), true)); + $this->assertEquals($expected, \json_decode(json: \json_encode(value: $source->jsonSerialize()), associative: true)); } protected function setUp(): void { parent::setUp(); - $this->factory = new FileSourceFactory($this->createDirectories()); + $this->factory = new FileSourceFactory(dirs: $this->createDirectories()); } } diff --git a/tests/src/Unit/Source/GitDiff/Fetcher/Source/CommitGitSourceTest.php b/tests/src/Unit/Source/GitDiff/Fetcher/Source/CommitGitSourceTest.php index b648f2d4..e23893f5 100644 --- a/tests/src/Unit/Source/GitDiff/Fetcher/Source/CommitGitSourceTest.php +++ b/tests/src/Unit/Source/GitDiff/Fetcher/Source/CommitGitSourceTest.php @@ -17,28 +17,28 @@ final class CommitGitSourceTest extends GitSourceTestCase #[Test] public function it_should_support_basic_commit_range(): void { - $this->assertTrue($this->commitGitSource->supports('HEAD~1..HEAD')); - $this->assertTrue($this->commitGitSource->supports('main..HEAD')); - $this->assertTrue($this->commitGitSource->supports('master..HEAD')); - $this->assertTrue($this->commitGitSource->supports('develop..HEAD')); + $this->assertTrue($this->commitGitSource->supports(commitReference: 'HEAD~1..HEAD')); + $this->assertTrue($this->commitGitSource->supports(commitReference: 'main..HEAD')); + $this->assertTrue($this->commitGitSource->supports(commitReference: 'master..HEAD')); + $this->assertTrue($this->commitGitSource->supports(commitReference: 'develop..HEAD')); } #[Test] public function it_should_support_commit_hash(): void { - $this->assertTrue($this->commitGitSource->supports('abcdef1')); - $this->assertTrue($this->commitGitSource->supports('abcdef1234567890')); - $this->assertTrue($this->commitGitSource->supports('abcdef1234567890abcdef1234567890abcdef12')); + $this->assertTrue($this->commitGitSource->supports(commitReference: 'abcdef1')); + $this->assertTrue($this->commitGitSource->supports(commitReference: 'abcdef1234567890')); + $this->assertTrue($this->commitGitSource->supports(commitReference: 'abcdef1234567890abcdef1234567890abcdef12')); } #[Test] public function it_should_not_support_other_formats(): void { - $this->assertFalse($this->commitGitSource->supports('')); - $this->assertFalse($this->commitGitSource->supports('--cached')); - $this->assertFalse($this->commitGitSource->supports('stash@{0}')); - $this->assertFalse($this->commitGitSource->supports('HEAD@{1.week.ago}..HEAD')); - $this->assertFalse($this->commitGitSource->supports('abc123 -- path/to/file')); + $this->assertFalse($this->commitGitSource->supports(commitReference: '')); + $this->assertFalse($this->commitGitSource->supports(commitReference: '--cached')); + $this->assertFalse($this->commitGitSource->supports(commitReference: 'stash@{0}')); + $this->assertFalse($this->commitGitSource->supports(commitReference: 'HEAD@{1.week.ago}..HEAD')); + $this->assertFalse($this->commitGitSource->supports(commitReference: 'abc123 -- path/to/file')); } #[Test] @@ -50,7 +50,7 @@ public function it_should_get_changed_files_in_commit_range(): void $this->mockChangedFiles($expectedCommand, $expectedFiles); // Get the changed files - $changedFiles = $this->commitGitSource->getChangedFiles($this->repoDir, 'HEAD~1..HEAD'); + $changedFiles = $this->commitGitSource->getChangedFiles(repository: $this->repoDir, commitReference: 'HEAD~1..HEAD'); // Verify that test2.txt is in the changed files $this->assertCount(1, $changedFiles); @@ -66,7 +66,7 @@ public function it_should_get_file_diff_for_specific_file(): void $this->mockFileDiff($expectedCommand, $expectedDiff); // Get the diff for the file - $diff = $this->commitGitSource->getFileDiff($this->repoDir, 'HEAD~1..HEAD', 'test.txt'); + $diff = $this->commitGitSource->getFileDiff(repository: $this->repoDir, commitReference: 'HEAD~1..HEAD', file: 'test.txt'); // Verify that the diff contains expected changes $this->assertStringContainsString('-Original content', $diff); @@ -79,23 +79,23 @@ public function it_should_format_reference_for_display(): void // Test common formats $this->assertSame( 'Changes in last commit', - $this->commitGitSource->formatReferenceForDisplay('HEAD~1..HEAD'), + $this->commitGitSource->formatReferenceForDisplay(commitReference: 'HEAD~1..HEAD'), ); $this->assertSame( 'Changes in last 5 commits', - $this->commitGitSource->formatReferenceForDisplay('HEAD~5..HEAD'), + $this->commitGitSource->formatReferenceForDisplay(commitReference: 'HEAD~5..HEAD'), ); $this->assertSame( 'Changes in changes since diverging from main', - $this->commitGitSource->formatReferenceForDisplay('main..HEAD'), + $this->commitGitSource->formatReferenceForDisplay(commitReference: 'main..HEAD'), ); // Test custom format $this->assertSame( 'Changes in commit range: custom..range', - $this->commitGitSource->formatReferenceForDisplay('custom..range'), + $this->commitGitSource->formatReferenceForDisplay(commitReference: 'custom..range'), ); } @@ -112,8 +112,8 @@ public function it_should_get_changes_for_specific_commit_hash(): void // Get the changed files for the specific commit $changedFiles = $this->commitGitSource->getChangedFiles( - $this->repoDir, - $commitHash . '~1..' . $commitHash, + repository: $this->repoDir, + commitReference: $commitHash . '~1..' . $commitHash, ); // Verify that only specific.txt is in the changed files @@ -125,6 +125,6 @@ public function it_should_get_changes_for_specific_commit_hash(): void protected function setUp(): void { parent::setUp(); - $this->commitGitSource = new CommitGitSource($this->commandExecutorMock, new Files(), $this->logger); + $this->commitGitSource = new CommitGitSource(commandsExecutor: $this->commandExecutorMock, files: new Files(), logger: $this->logger); } } diff --git a/tests/src/Unit/Source/GitDiff/Fetcher/Source/FileAtCommitGitSourceTest.php b/tests/src/Unit/Source/GitDiff/Fetcher/Source/FileAtCommitGitSourceTest.php index f2673112..6043db2c 100644 --- a/tests/src/Unit/Source/GitDiff/Fetcher/Source/FileAtCommitGitSourceTest.php +++ b/tests/src/Unit/Source/GitDiff/Fetcher/Source/FileAtCommitGitSourceTest.php @@ -17,20 +17,20 @@ final class FileAtCommitGitSourceTest extends GitSourceTestCase #[Test] public function it_should_support_commit_with_path_format(): void { - $this->assertTrue($this->fileAtCommitGitSource->supports('abcdef1 -- path/to/file.php')); - $this->assertTrue($this->fileAtCommitGitSource->supports('HEAD -- src/')); - $this->assertTrue($this->fileAtCommitGitSource->supports('main -- vendor/')); + $this->assertTrue($this->fileAtCommitGitSource->supports(commitReference: 'abcdef1 -- path/to/file.php')); + $this->assertTrue($this->fileAtCommitGitSource->supports(commitReference: 'HEAD -- src/')); + $this->assertTrue($this->fileAtCommitGitSource->supports(commitReference: 'main -- vendor/')); } #[Test] public function it_should_not_support_other_formats(): void { - $this->assertFalse($this->fileAtCommitGitSource->supports('')); - $this->assertFalse($this->fileAtCommitGitSource->supports('--cached')); - $this->assertFalse($this->fileAtCommitGitSource->supports('stash@{0}')); - $this->assertFalse($this->fileAtCommitGitSource->supports('HEAD~1..HEAD')); - $this->assertFalse($this->fileAtCommitGitSource->supports('HEAD@{1.week.ago}..HEAD')); - $this->assertFalse($this->fileAtCommitGitSource->supports('abcdef1')); + $this->assertFalse($this->fileAtCommitGitSource->supports(commitReference: '')); + $this->assertFalse($this->fileAtCommitGitSource->supports(commitReference: '--cached')); + $this->assertFalse($this->fileAtCommitGitSource->supports(commitReference: 'stash@{0}')); + $this->assertFalse($this->fileAtCommitGitSource->supports(commitReference: 'HEAD~1..HEAD')); + $this->assertFalse($this->fileAtCommitGitSource->supports(commitReference: 'HEAD@{1.week.ago}..HEAD')); + $this->assertFalse($this->fileAtCommitGitSource->supports(commitReference: 'abcdef1')); } #[Test] @@ -46,7 +46,7 @@ public function it_should_get_file_at_specific_commit(): void // Get only src files at this commit $commitReference = $commitHash . ' -- src/'; - $files = $this->fileAtCommitGitSource->getChangedFiles($this->repoDir, $commitReference); + $files = $this->fileAtCommitGitSource->getChangedFiles(repository: $this->repoDir, commitReference: $commitReference); // Verify that only src/test1.php is returned $this->assertCount(1, $files); @@ -69,7 +69,7 @@ public function it_should_get_multiple_files_matching_pattern(): void // Get only model files $commitReference = $commitHash . ' -- src/models/'; - $files = $this->fileAtCommitGitSource->getChangedFiles($this->repoDir, $commitReference); + $files = $this->fileAtCommitGitSource->getChangedFiles(repository: $this->repoDir, commitReference: $commitReference); // Verify that only model files are returned (and the commit hash is filtered out) $this->assertCount(2, $files); @@ -91,7 +91,7 @@ public function it_should_get_file_content_at_commit(): void // Get the file at the first commit $commitReference = $commitHash . ' -- test.php'; - $content = $this->fileAtCommitGitSource->getFileDiff($this->repoDir, $commitReference, 'test.php'); + $content = $this->fileAtCommitGitSource->getFileDiff(repository: $this->repoDir, commitReference: $commitReference, file: 'test.php'); // Verify that the original content is returned $this->assertStringContainsString('fileAtCommitGitSource->getFileDiff($this->repoDir, $commitReference, 'vendor/file2.php'); + $content = $this->fileAtCommitGitSource->getFileDiff(repository: $this->repoDir, commitReference: $commitReference, file: 'vendor/file2.php'); // Verify that an empty string is returned $this->assertSame('', $content); @@ -117,7 +117,7 @@ public function it_should_return_empty_for_non_matching_file(): void public function it_should_format_reference_for_display(): void { $commitRef = 'abc1234 -- src/file.php'; - $displayText = $this->fileAtCommitGitSource->formatReferenceForDisplay($commitRef); + $displayText = $this->fileAtCommitGitSource->formatReferenceForDisplay(commitReference: $commitRef); $this->assertSame('Files at commit abc1234 with path: src/file.php', $displayText); } @@ -126,6 +126,6 @@ public function it_should_format_reference_for_display(): void protected function setUp(): void { parent::setUp(); - $this->fileAtCommitGitSource = new FileAtCommitGitSource($this->commandExecutorMock, new Files(), $this->logger); + $this->fileAtCommitGitSource = new FileAtCommitGitSource(commandsExecutor: $this->commandExecutorMock, files: new Files(), logger: $this->logger); } } diff --git a/tests/src/Unit/Source/GitDiff/Fetcher/Source/GitSourceTestCase.php b/tests/src/Unit/Source/GitDiff/Fetcher/Source/GitSourceTestCase.php index 2429fa96..baa83bed 100644 --- a/tests/src/Unit/Source/GitDiff/Fetcher/Source/GitSourceTestCase.php +++ b/tests/src/Unit/Source/GitDiff/Fetcher/Source/GitSourceTestCase.php @@ -49,8 +49,8 @@ protected function mockChangedFiles(string $command, array $files): void $this->commandExecutorMock ->expects($this->atLeastOnce()) ->method('executeString') - ->with(new Command($this->repoDir, $command)) - ->willReturn(\implode("\n", $files)); + ->with(new Command(repository: $this->repoDir, command: $command)) + ->willReturn(\implode(separator: "\n", array: $files)); } /** @@ -64,7 +64,7 @@ protected function mockFileDiff(string $command, string $diff): void $this->commandExecutorMock ->expects($this->atLeastOnce()) ->method('executeString') - ->with(new Command($this->repoDir, $command)) + ->with(new Command(repository: $this->repoDir, command: $command)) ->willReturn($diff); } @@ -77,7 +77,7 @@ protected function mockCommitHash(string $hash): string { $this->commandExecutorMock ->method('executeString') - ->with(new Command($this->repoDir, 'git rev-parse HEAD')) + ->with(new Command(repository: $this->repoDir, command: 'git rev-parse HEAD')) ->willReturn($hash); return $hash; @@ -94,7 +94,7 @@ protected function mockGitCommand(string $repository, string $command, array $re { $this->commandExecutorMock ->method('executeString') - ->with(new Command($this->repoDir, $command)) + ->with(new Command(repository: $this->repoDir, command: $command)) ->willReturn($result); } } diff --git a/tests/src/Unit/Source/GitDiff/Fetcher/Source/StagedGitSourceTest.php b/tests/src/Unit/Source/GitDiff/Fetcher/Source/StagedGitSourceTest.php index a3add541..316de26c 100644 --- a/tests/src/Unit/Source/GitDiff/Fetcher/Source/StagedGitSourceTest.php +++ b/tests/src/Unit/Source/GitDiff/Fetcher/Source/StagedGitSourceTest.php @@ -17,18 +17,18 @@ final class StagedGitSourceTest extends GitSourceTestCase #[Test] public function it_should_support_staged_references(): void { - $this->assertTrue($this->stagedGitSource->supports('--cached')); - $this->assertTrue($this->stagedGitSource->supports('staged')); + $this->assertTrue($this->stagedGitSource->supports(commitReference: '--cached')); + $this->assertTrue($this->stagedGitSource->supports(commitReference: 'staged')); } #[Test] public function it_should_not_support_other_formats(): void { - $this->assertFalse($this->stagedGitSource->supports('')); - $this->assertFalse($this->stagedGitSource->supports('HEAD~1..HEAD')); - $this->assertFalse($this->stagedGitSource->supports('stash@{0}')); - $this->assertFalse($this->stagedGitSource->supports('HEAD@{1.week.ago}..HEAD')); - $this->assertFalse($this->stagedGitSource->supports('abcdef1 -- path/to/file')); + $this->assertFalse($this->stagedGitSource->supports(commitReference: '')); + $this->assertFalse($this->stagedGitSource->supports(commitReference: 'HEAD~1..HEAD')); + $this->assertFalse($this->stagedGitSource->supports(commitReference: 'stash@{0}')); + $this->assertFalse($this->stagedGitSource->supports(commitReference: 'HEAD@{1.week.ago}..HEAD')); + $this->assertFalse($this->stagedGitSource->supports(commitReference: 'abcdef1 -- path/to/file')); } #[Test] @@ -40,7 +40,7 @@ public function it_should_get_staged_files(): void $this->mockChangedFiles($expectedCommand, $expectedFiles); // Get the staged files - $stagedFiles = $this->stagedGitSource->getChangedFiles($this->repoDir, '--cached'); + $stagedFiles = $this->stagedGitSource->getChangedFiles(repository: $this->repoDir, commitReference: '--cached'); // Verify that only staged.txt is in the list $this->assertCount(1, $stagedFiles); @@ -56,7 +56,7 @@ public function it_should_get_staged_file_diff(): void $this->mockFileDiff($expectedCommand, $expectedDiff); // Get the diff for the staged file - $diff = $this->stagedGitSource->getFileDiff($this->repoDir, '--cached', 'existing.txt'); + $diff = $this->stagedGitSource->getFileDiff(repository: $this->repoDir, commitReference: '--cached', file: 'existing.txt'); // Verify that the diff contains expected changes $this->assertStringContainsString('-Original content', $diff); @@ -68,12 +68,12 @@ public function it_should_format_reference_for_display(): void { $this->assertSame( 'Changes staged for commit', - $this->stagedGitSource->formatReferenceForDisplay('--cached'), + $this->stagedGitSource->formatReferenceForDisplay(commitReference: '--cached'), ); $this->assertSame( 'Changes staged for commit', - $this->stagedGitSource->formatReferenceForDisplay('staged'), + $this->stagedGitSource->formatReferenceForDisplay(commitReference: 'staged'), ); } @@ -86,7 +86,7 @@ public function it_should_handle_new_staged_files(): void $this->mockFileDiff($expectedCommand, $expectedDiff); // Get the diff for the new staged file - $diff = $this->stagedGitSource->getFileDiff($this->repoDir, '--cached', 'new-staged.txt'); + $diff = $this->stagedGitSource->getFileDiff(repository: $this->repoDir, commitReference: '--cached', file: 'new-staged.txt'); // Verify that the diff shows the new file content $this->assertStringContainsString('+New staged content', $diff); @@ -100,7 +100,7 @@ public function it_should_handle_no_staged_changes(): void $this->mockChangedFiles($expectedCommand, []); // Get staged files when there are none - $stagedFiles = $this->stagedGitSource->getChangedFiles($this->repoDir, '--cached'); + $stagedFiles = $this->stagedGitSource->getChangedFiles(repository: $this->repoDir, commitReference: '--cached'); // Verify that the list is empty $this->assertEmpty($stagedFiles); @@ -115,7 +115,7 @@ public function it_should_handle_multiple_staged_files(): void $this->mockChangedFiles($expectedCommand, $expectedFiles); // Get the staged files - $stagedFiles = $this->stagedGitSource->getChangedFiles($this->repoDir, '--cached'); + $stagedFiles = $this->stagedGitSource->getChangedFiles(repository: $this->repoDir, commitReference: '--cached'); // Verify that all staged files are in the list $this->assertCount(3, $stagedFiles); @@ -128,6 +128,6 @@ public function it_should_handle_multiple_staged_files(): void protected function setUp(): void { parent::setUp(); - $this->stagedGitSource = new StagedGitSource($this->commandExecutorMock, new Files(), $this->logger); + $this->stagedGitSource = new StagedGitSource(commandsExecutor: $this->commandExecutorMock, files: new Files(), logger: $this->logger); } } diff --git a/tests/src/Unit/Source/GitDiff/Fetcher/Source/StashGitSourceTest.php b/tests/src/Unit/Source/GitDiff/Fetcher/Source/StashGitSourceTest.php index 76a71364..c31998a7 100644 --- a/tests/src/Unit/Source/GitDiff/Fetcher/Source/StashGitSourceTest.php +++ b/tests/src/Unit/Source/GitDiff/Fetcher/Source/StashGitSourceTest.php @@ -17,20 +17,20 @@ final class StashGitSourceTest extends GitSourceTestCase #[Test] public function it_should_support_stash_references(): void { - $this->assertTrue($this->stashGitSource->supports('stash@{0}')); - $this->assertTrue($this->stashGitSource->supports('stash@{1}')); - $this->assertTrue($this->stashGitSource->supports('stash@{0}..stash@{2}')); - $this->assertTrue($this->stashGitSource->supports('stash@{/message}')); + $this->assertTrue($this->stashGitSource->supports(commitReference: 'stash@{0}')); + $this->assertTrue($this->stashGitSource->supports(commitReference: 'stash@{1}')); + $this->assertTrue($this->stashGitSource->supports(commitReference: 'stash@{0}..stash@{2}')); + $this->assertTrue($this->stashGitSource->supports(commitReference: 'stash@{/message}')); } #[Test] public function it_should_not_support_other_formats(): void { - $this->assertFalse($this->stashGitSource->supports('')); - $this->assertFalse($this->stashGitSource->supports('--cached')); - $this->assertFalse($this->stashGitSource->supports('HEAD~1..HEAD')); - $this->assertFalse($this->stashGitSource->supports('HEAD@{1.week.ago}..HEAD')); - $this->assertFalse($this->stashGitSource->supports('abcdef1 -- path/to/file')); + $this->assertFalse($this->stashGitSource->supports(commitReference: '')); + $this->assertFalse($this->stashGitSource->supports(commitReference: '--cached')); + $this->assertFalse($this->stashGitSource->supports(commitReference: 'HEAD~1..HEAD')); + $this->assertFalse($this->stashGitSource->supports(commitReference: 'HEAD@{1.week.ago}..HEAD')); + $this->assertFalse($this->stashGitSource->supports(commitReference: 'abcdef1 -- path/to/file')); } #[Test] @@ -42,7 +42,7 @@ public function it_should_get_files_from_stash(): void $this->mockChangedFiles($expectedCommand, $expectedFiles); // Get the files from the stash - $stashedFiles = $this->stashGitSource->getChangedFiles($this->repoDir, 'stash@{0}'); + $stashedFiles = $this->stashGitSource->getChangedFiles(repository: $this->repoDir, commitReference: 'stash@{0}'); // Verify that both files are in the stash $this->assertContains('stashed.txt', $stashedFiles); @@ -58,7 +58,7 @@ public function it_should_get_stash_diff_for_specific_file(): void $this->mockFileDiff($expectedCommand, $expectedDiff); // Get the diff for the stashed file - $diff = $this->stashGitSource->getFileDiff($this->repoDir, 'stash@{0}', 'stashed-diff.txt'); + $diff = $this->stashGitSource->getFileDiff(repository: $this->repoDir, commitReference: 'stash@{0}', file: 'stashed-diff.txt'); // Verify that the diff contains expected changes $this->assertStringContainsString('Modified content for stashing', $diff); @@ -70,23 +70,23 @@ public function it_should_format_reference_for_display(): void // Test common formats $this->assertSame( 'Changes in latest stash', - $this->stashGitSource->formatReferenceForDisplay('stash@{0}'), + $this->stashGitSource->formatReferenceForDisplay(commitReference: 'stash@{0}'), ); $this->assertSame( 'Changes in second most recent stash', - $this->stashGitSource->formatReferenceForDisplay('stash@{1}'), + $this->stashGitSource->formatReferenceForDisplay(commitReference: 'stash@{1}'), ); $this->assertSame( 'Changes in latest 2 stashes', - $this->stashGitSource->formatReferenceForDisplay('stash@{0}..stash@{1}'), + $this->stashGitSource->formatReferenceForDisplay(commitReference: 'stash@{0}..stash@{1}'), ); // Test custom format $this->assertSame( 'Changes in stash: stash@{/custom-message}', - $this->stashGitSource->formatReferenceForDisplay('stash@{/custom-message}'), + $this->stashGitSource->formatReferenceForDisplay(commitReference: 'stash@{/custom-message}'), ); } @@ -98,7 +98,7 @@ public function it_should_return_empty_array_for_non_existent_stash(): void $this->mockChangedFiles($expectedCommand, []); // Try to get files from a non-existent stash index - $files = $this->stashGitSource->getChangedFiles($this->repoDir, 'stash@{100}'); + $files = $this->stashGitSource->getChangedFiles(repository: $this->repoDir, commitReference: 'stash@{100}'); // Verify that an empty array is returned $this->assertEmpty($files); @@ -112,7 +112,7 @@ public function it_should_return_empty_string_for_non_existent_stash_diff(): voi $this->mockFileDiff($expectedCommand, ''); // Try to get diff from a non-existent stash - $diff = $this->stashGitSource->getFileDiff($this->repoDir, 'stash@{100}', 'file.txt'); + $diff = $this->stashGitSource->getFileDiff(repository: $this->repoDir, commitReference: 'stash@{100}', file: 'file.txt'); // Verify that an empty string is returned $this->assertSame('', $diff); @@ -122,6 +122,6 @@ public function it_should_return_empty_string_for_non_existent_stash_diff(): voi protected function setUp(): void { parent::setUp(); - $this->stashGitSource = new StashGitSource($this->commandExecutorMock, new Files(), $this->logger); + $this->stashGitSource = new StashGitSource(commandsExecutor: $this->commandExecutorMock, files: new Files(), logger: $this->logger); } } diff --git a/tests/src/Unit/Source/GitDiff/Fetcher/Source/TimeRangeGitSourceTest.php b/tests/src/Unit/Source/GitDiff/Fetcher/Source/TimeRangeGitSourceTest.php index 0b006388..06b95747 100644 --- a/tests/src/Unit/Source/GitDiff/Fetcher/Source/TimeRangeGitSourceTest.php +++ b/tests/src/Unit/Source/GitDiff/Fetcher/Source/TimeRangeGitSourceTest.php @@ -17,20 +17,20 @@ final class TimeRangeGitSourceTest extends GitSourceTestCase #[Test] public function it_should_support_time_based_ranges(): void { - $this->assertTrue($this->timeRangeGitSource->supports('HEAD@{1.week.ago}..HEAD')); - $this->assertTrue($this->timeRangeGitSource->supports('HEAD@{1.days.ago}..HEAD@{0.days.ago}')); - $this->assertTrue($this->timeRangeGitSource->supports('HEAD@{0:00:00}..HEAD')); - $this->assertTrue($this->timeRangeGitSource->supports('--since=2023-01-01')); + $this->assertTrue($this->timeRangeGitSource->supports(commitReference: 'HEAD@{1.week.ago}..HEAD')); + $this->assertTrue($this->timeRangeGitSource->supports(commitReference: 'HEAD@{1.days.ago}..HEAD@{0.days.ago}')); + $this->assertTrue($this->timeRangeGitSource->supports(commitReference: 'HEAD@{0:00:00}..HEAD')); + $this->assertTrue($this->timeRangeGitSource->supports(commitReference: '--since=2023-01-01')); } #[Test] public function it_should_not_support_other_formats(): void { - $this->assertFalse($this->timeRangeGitSource->supports('')); - $this->assertFalse($this->timeRangeGitSource->supports('--cached')); - $this->assertFalse($this->timeRangeGitSource->supports('HEAD~1..HEAD')); - $this->assertFalse($this->timeRangeGitSource->supports('stash@{0}')); - $this->assertFalse($this->timeRangeGitSource->supports('abcdef1 -- path/to/file')); + $this->assertFalse($this->timeRangeGitSource->supports(commitReference: '')); + $this->assertFalse($this->timeRangeGitSource->supports(commitReference: '--cached')); + $this->assertFalse($this->timeRangeGitSource->supports(commitReference: 'HEAD~1..HEAD')); + $this->assertFalse($this->timeRangeGitSource->supports(commitReference: 'stash@{0}')); + $this->assertFalse($this->timeRangeGitSource->supports(commitReference: 'abcdef1 -- path/to/file')); } #[Test] @@ -43,8 +43,8 @@ public function it_should_get_changed_files_for_time_range(): void // Get files changed using --since format $changedFiles = $this->timeRangeGitSource->getChangedFiles( - $this->repoDir, - '--since=1.minute.ago', + repository: $this->repoDir, + commitReference: '--since=1.minute.ago', ); // Verify both files are included in the time range (empty lines filtered out) @@ -63,8 +63,8 @@ public function it_should_get_changed_files_for_head_time_range(): void // Get files changed in the time range $changedFiles = $this->timeRangeGitSource->getChangedFiles( - $this->repoDir, - 'HEAD@{1.week.ago}..HEAD', + repository: $this->repoDir, + commitReference: 'HEAD@{1.week.ago}..HEAD', ); // Verify both files are included @@ -83,9 +83,9 @@ public function it_should_get_file_diff_for_time_range(): void // Get the diff for this file in the time range $diff = $this->timeRangeGitSource->getFileDiff( - $this->repoDir, - '--since=1.minute.ago', - 'time-diff.txt', + repository: $this->repoDir, + commitReference: '--since=1.minute.ago', + file: 'time-diff.txt', ); // Verify that the diff contains the expected changes @@ -103,9 +103,9 @@ public function it_should_get_file_diff_for_head_time_range(): void // Get the diff for this file in the HEAD time range $diff = $this->timeRangeGitSource->getFileDiff( - $this->repoDir, - 'HEAD@{1.week.ago}..HEAD', - 'time-diff.txt', + repository: $this->repoDir, + commitReference: 'HEAD@{1.week.ago}..HEAD', + file: 'time-diff.txt', ); // Verify that the diff contains the expected changes @@ -119,29 +119,29 @@ public function it_should_format_reference_for_display(): void // Test common formats $this->assertSame( 'Changes from today', - $this->timeRangeGitSource->formatReferenceForDisplay('HEAD@{0:00:00}..HEAD'), + $this->timeRangeGitSource->formatReferenceForDisplay(commitReference: 'HEAD@{0:00:00}..HEAD'), ); $this->assertSame( 'Changes from last week', - $this->timeRangeGitSource->formatReferenceForDisplay('HEAD@{1.week.ago}..HEAD'), + $this->timeRangeGitSource->formatReferenceForDisplay(commitReference: 'HEAD@{1.week.ago}..HEAD'), ); $this->assertSame( 'Changes from last month', - $this->timeRangeGitSource->formatReferenceForDisplay('HEAD@{1.month.ago}..HEAD'), + $this->timeRangeGitSource->formatReferenceForDisplay(commitReference: 'HEAD@{1.month.ago}..HEAD'), ); // Test --since format $this->assertSame( 'Changes since 2023-01-01', - $this->timeRangeGitSource->formatReferenceForDisplay('--since=2023-01-01'), + $this->timeRangeGitSource->formatReferenceForDisplay(commitReference: '--since=2023-01-01'), ); // Test custom format $this->assertSame( 'Changes in time range: custom@{time}..range', - $this->timeRangeGitSource->formatReferenceForDisplay('custom@{time}..range'), + $this->timeRangeGitSource->formatReferenceForDisplay(commitReference: 'custom@{time}..range'), ); } @@ -154,8 +154,8 @@ public function it_should_handle_empty_time_range(): void // Try to get changes in a time range with no commits $changedFiles = $this->timeRangeGitSource->getChangedFiles( - $this->repoDir, - '--since=2099-01-01', // Future date with no changes + repository: $this->repoDir, + commitReference: '--since=2099-01-01', // Future date with no changes ); // Verify that an empty array is returned @@ -166,6 +166,6 @@ public function it_should_handle_empty_time_range(): void protected function setUp(): void { parent::setUp(); - $this->timeRangeGitSource = new TimeRangeGitSource($this->commandExecutorMock, new Files(), $this->logger); + $this->timeRangeGitSource = new TimeRangeGitSource(commandsExecutor: $this->commandExecutorMock, files: new Files(), logger: $this->logger); } } diff --git a/tests/src/Unit/Source/GitDiff/Fetcher/Source/UnstagedGitSourceTest.php b/tests/src/Unit/Source/GitDiff/Fetcher/Source/UnstagedGitSourceTest.php index 4635d910..8ae160ab 100644 --- a/tests/src/Unit/Source/GitDiff/Fetcher/Source/UnstagedGitSourceTest.php +++ b/tests/src/Unit/Source/GitDiff/Fetcher/Source/UnstagedGitSourceTest.php @@ -17,18 +17,18 @@ final class UnstagedGitSourceTest extends GitSourceTestCase #[Test] public function it_should_support_unstaged_references(): void { - $this->assertTrue($this->unstagedGitSource->supports('')); - $this->assertTrue($this->unstagedGitSource->supports('unstaged')); + $this->assertTrue($this->unstagedGitSource->supports(commitReference: '')); + $this->assertTrue($this->unstagedGitSource->supports(commitReference: 'unstaged')); } #[Test] public function it_should_not_support_other_formats(): void { - $this->assertFalse($this->unstagedGitSource->supports('--cached')); - $this->assertFalse($this->unstagedGitSource->supports('HEAD~1..HEAD')); - $this->assertFalse($this->unstagedGitSource->supports('stash@{0}')); - $this->assertFalse($this->unstagedGitSource->supports('HEAD@{1.week.ago}..HEAD')); - $this->assertFalse($this->unstagedGitSource->supports('abcdef1 -- path/to/file')); + $this->assertFalse($this->unstagedGitSource->supports(commitReference: '--cached')); + $this->assertFalse($this->unstagedGitSource->supports(commitReference: 'HEAD~1..HEAD')); + $this->assertFalse($this->unstagedGitSource->supports(commitReference: 'stash@{0}')); + $this->assertFalse($this->unstagedGitSource->supports(commitReference: 'HEAD@{1.week.ago}..HEAD')); + $this->assertFalse($this->unstagedGitSource->supports(commitReference: 'abcdef1 -- path/to/file')); } #[Test] @@ -40,7 +40,7 @@ public function it_should_get_unstaged_files(): void $this->mockChangedFiles($expectedCommand, $expectedFiles); // Get the unstaged files - $unstagedFiles = $this->unstagedGitSource->getChangedFiles($this->repoDir, ''); + $unstagedFiles = $this->unstagedGitSource->getChangedFiles(repository: $this->repoDir, commitReference: ''); // Verify that unstaged files are in the list $this->assertCount(2, $unstagedFiles); @@ -57,7 +57,7 @@ public function it_should_get_unstaged_file_diff(): void $this->mockFileDiff($expectedCommand, $expectedDiff); // Get the diff for the unstaged file - $diff = $this->unstagedGitSource->getFileDiff($this->repoDir, '', 'unstaged-diff.txt'); + $diff = $this->unstagedGitSource->getFileDiff(repository: $this->repoDir, commitReference: '', file: 'unstaged-diff.txt'); // Verify that the diff contains expected changes $this->assertStringContainsString('-Original unstaged content', $diff); @@ -69,12 +69,12 @@ public function it_should_format_reference_for_display(): void { $this->assertSame( 'Unstaged changes', - $this->unstagedGitSource->formatReferenceForDisplay(''), + $this->unstagedGitSource->formatReferenceForDisplay(commitReference: ''), ); $this->assertSame( 'Unstaged changes', - $this->unstagedGitSource->formatReferenceForDisplay('unstaged'), + $this->unstagedGitSource->formatReferenceForDisplay(commitReference: 'unstaged'), ); } @@ -87,7 +87,7 @@ public function it_should_handle_new_unstaged_files(): void $this->mockChangedFiles($expectedCommand, $expectedFiles); // Get the unstaged files - $unstagedFiles = $this->unstagedGitSource->getChangedFiles($this->repoDir, ''); + $unstagedFiles = $this->unstagedGitSource->getChangedFiles(repository: $this->repoDir, commitReference: ''); // Verify that the new file is in the unstaged files $this->assertContains('new-unstaged.txt', $unstagedFiles); @@ -101,7 +101,7 @@ public function it_should_handle_no_unstaged_changes(): void $this->mockChangedFiles($expectedCommand, []); // Get unstaged files when there are none - $unstagedFiles = $this->unstagedGitSource->getChangedFiles($this->repoDir, ''); + $unstagedFiles = $this->unstagedGitSource->getChangedFiles(repository: $this->repoDir, commitReference: ''); // Verify that the list is empty $this->assertEmpty($unstagedFiles); @@ -116,7 +116,7 @@ public function it_should_handle_multiple_unstaged_changes(): void $this->mockChangedFiles($expectedCommand, $expectedFiles); // Get all unstaged files - $unstagedFiles = $this->unstagedGitSource->getChangedFiles($this->repoDir, ''); + $unstagedFiles = $this->unstagedGitSource->getChangedFiles(repository: $this->repoDir, commitReference: ''); // Verify that all expected unstaged files are in the list $this->assertCount(3, $unstagedFiles); @@ -129,6 +129,6 @@ public function it_should_handle_multiple_unstaged_changes(): void protected function setUp(): void { parent::setUp(); - $this->unstagedGitSource = new UnstagedGitSource($this->commandExecutorMock, new Files(), $this->logger); + $this->unstagedGitSource = new UnstagedGitSource(commandsExecutor: $this->commandExecutorMock, files: new Files(), logger: $this->logger); } } diff --git a/tests/src/Unit/Source/GitDiff/RenderStrategy/LLMFriendlyRenderStrategyTest.php b/tests/src/Unit/Source/GitDiff/RenderStrategy/LLMFriendlyRenderStrategyTest.php index b3fc86f1..0b8254e8 100644 --- a/tests/src/Unit/Source/GitDiff/RenderStrategy/LLMFriendlyRenderStrategyTest.php +++ b/tests/src/Unit/Source/GitDiff/RenderStrategy/LLMFriendlyRenderStrategyTest.php @@ -20,7 +20,7 @@ final class LLMFriendlyRenderStrategyTest extends TestCase #[Test] public function it_should_handle_empty_diffs(): void { - $result = $this->strategy->render([], new RenderConfig(strategy: RenderStrategyEnum::LLM)); + $result = $this->strategy->render(diffs: [], config: new RenderConfig(strategy: RenderStrategyEnum::LLM)); $this->assertInstanceOf(ContentBuilder::class, $result); $this->assertStringContainsString( @@ -40,7 +40,7 @@ public function it_should_render_file_diffs_with_llm_friendly_format(): void ], ]; - $result = $this->strategy->render($diffs, new RenderConfig(strategy: RenderStrategyEnum::LLM)); + $result = $this->strategy->render(diffs: $diffs, config: new RenderConfig(strategy: RenderStrategyEnum::LLM)); $content = $this->getContentFromBuilder($result); $this->assertInstanceOf(ContentBuilder::class, $result); @@ -74,7 +74,7 @@ public function it_should_properly_handle_multiple_file_diffs(): void ], ]; - $result = $this->strategy->render($diffs, new RenderConfig(strategy: RenderStrategyEnum::LLM)); + $result = $this->strategy->render(diffs: $diffs, config: new RenderConfig(strategy: RenderStrategyEnum::LLM)); $content = $this->getContentFromBuilder($result); $this->assertInstanceOf(ContentBuilder::class, $result); @@ -95,7 +95,7 @@ public function it_should_handle_empty_diff_content_for_file(): void ], ]; - $result = $this->strategy->render($diffs, new RenderConfig(strategy: RenderStrategyEnum::LLM)); + $result = $this->strategy->render(diffs: $diffs, config: new RenderConfig(strategy: RenderStrategyEnum::LLM)); $content = $this->getContentFromBuilder($result); $this->assertInstanceOf(ContentBuilder::class, $result); diff --git a/tests/src/Unit/Source/GitDiff/RenderStrategy/RawRenderStrategyTest.php b/tests/src/Unit/Source/GitDiff/RenderStrategy/RawRenderStrategyTest.php index 5144456c..3baa24f3 100644 --- a/tests/src/Unit/Source/GitDiff/RenderStrategy/RawRenderStrategyTest.php +++ b/tests/src/Unit/Source/GitDiff/RenderStrategy/RawRenderStrategyTest.php @@ -28,7 +28,7 @@ public function it_should_render_file_diffs_in_raw_format(): void ], ]; - $result = $this->strategy->render($diffs, new RenderConfig(strategy: RenderStrategyEnum::Raw)); + $result = $this->strategy->render(diffs: $diffs, config: new RenderConfig(strategy: RenderStrategyEnum::Raw)); $content = $this->getContentFromBuilder($result); $this->assertInstanceOf(ContentBuilder::class, $result); @@ -60,7 +60,7 @@ public function it_should_properly_handle_multiple_file_diffs(): void ], ]; - $result = $this->strategy->render($diffs, new RenderConfig(strategy: RenderStrategyEnum::Raw)); + $result = $this->strategy->render(diffs: $diffs, config: new RenderConfig(strategy: RenderStrategyEnum::Raw)); $content = $this->getContentFromBuilder($result); $this->assertInstanceOf(ContentBuilder::class, $result); @@ -73,7 +73,7 @@ public function it_should_properly_handle_multiple_file_diffs(): void #[Test] public function it_should_handle_empty_diff_array(): void { - $result = $this->strategy->render([], new RenderConfig(strategy: RenderStrategyEnum::Raw)); + $result = $this->strategy->render(diffs: [], config: new RenderConfig(strategy: RenderStrategyEnum::Raw)); $this->assertInstanceOf(ContentBuilder::class, $result); // Empty diff array should result in empty content diff --git a/tests/src/Unit/Source/GitDiff/RenderStrategy/RenderStrategyFactoryTest.php b/tests/src/Unit/Source/GitDiff/RenderStrategy/RenderStrategyFactoryTest.php index 1342bdb3..9518345d 100644 --- a/tests/src/Unit/Source/GitDiff/RenderStrategy/RenderStrategyFactoryTest.php +++ b/tests/src/Unit/Source/GitDiff/RenderStrategy/RenderStrategyFactoryTest.php @@ -21,7 +21,7 @@ final class RenderStrategyFactoryTest extends TestCase #[Test] public function it_should_create_raw_render_strategy(): void { - $strategy = $this->factory->create(RenderStrategyEnum::Raw); + $strategy = $this->factory->create(strategy: RenderStrategyEnum::Raw); $this->assertInstanceOf(RenderStrategyInterface::class, $strategy); $this->assertInstanceOf(RawRenderStrategy::class, $strategy); @@ -30,7 +30,7 @@ public function it_should_create_raw_render_strategy(): void #[Test] public function it_should_create_llm_friendly_render_strategy(): void { - $strategy = $this->factory->create(RenderStrategyEnum::LLM); + $strategy = $this->factory->create(strategy: RenderStrategyEnum::LLM); $this->assertInstanceOf(RenderStrategyInterface::class, $strategy); $this->assertInstanceOf(LLMFriendlyRenderStrategy::class, $strategy); diff --git a/tests/src/Unit/Source/TextSourceFromArrayTest.php b/tests/src/Unit/Source/TextSourceFromArrayTest.php index d36eff89..cd69e5e2 100644 --- a/tests/src/Unit/Source/TextSourceFromArrayTest.php +++ b/tests/src/Unit/Source/TextSourceFromArrayTest.php @@ -99,6 +99,6 @@ protected function setUp(): void { parent::setUp(); - $this->factory = new TextSourceFactory($this->createDirectories()); + $this->factory = new TextSourceFactory(dirs: $this->createDirectories()); } } diff --git a/tests/src/Unit/Source/Url/UrlSourceFetcherTest.php b/tests/src/Unit/Source/Url/UrlSourceFetcherTest.php index e19afe51..93e7cda9 100644 --- a/tests/src/Unit/Source/Url/UrlSourceFetcherTest.php +++ b/tests/src/Unit/Source/Url/UrlSourceFetcherTest.php @@ -36,7 +36,7 @@ class UrlSourceFetcherTest extends TestCase #[Test] public function it_should_support_url_sources(): void { - $urlSource = new UrlSource(['https://example.com']); + $urlSource = new UrlSource(urls: ['https://example.com']); $this->logger ->expects($this->once()) @@ -46,7 +46,7 @@ public function it_should_support_url_sources(): void 'isSupported' => true, ]); - $this->assertTrue($this->fetcher->supports($urlSource)); + $this->assertTrue($this->fetcher->supports(source: $urlSource)); } #[Test] @@ -62,7 +62,7 @@ public function it_should_not_support_other_sources(): void 'isSupported' => false, ]); - $this->assertFalse($this->fetcher->supports($otherSource)); + $this->assertFalse($this->fetcher->supports(source: $otherSource)); } #[Test] @@ -73,7 +73,7 @@ public function it_should_throw_exception_for_invalid_source_type(): void $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Source must be an instance of UrlSource'); - $this->fetcher->fetch($invalidSource, $this->modifiersApplier); + $this->fetcher->fetch(source: $invalidSource, modifiersApplier: $this->modifiersApplier); } #[Test] @@ -118,7 +118,7 @@ public function it_should_fetch_single_url_content(): void ->willReturn($modifiedContent); // Act - $result = $this->fetcher->fetch($urlSource, $this->modifiersApplier); + $result = $this->fetcher->fetch(source: $urlSource, modifiersApplier: $this->modifiersApplier); // Assert $this->assertStringContainsString('Test description', $result); @@ -167,7 +167,7 @@ public function it_should_extract_content_using_selector(): void $this->modifiersApplier->method('apply')->willReturn($modifiedContent); // Act - $result = $this->fetcher->fetch($urlSource, $this->modifiersApplier); + $result = $this->fetcher->fetch(source: $urlSource, modifiersApplier: $this->modifiersApplier); // Assert $this->assertStringContainsString("URL: {$url} (selector: {$selector})", $result); @@ -204,7 +204,7 @@ public function it_should_handle_empty_selector_result(): void ->willReturn(''); // Act - $result = $this->fetcher->fetch($urlSource, $this->modifiersApplier); + $result = $this->fetcher->fetch(source: $urlSource, modifiersApplier: $this->modifiersApplier); // Assert $this->assertStringContainsString("URL: {$url}", $result); @@ -231,7 +231,7 @@ public function it_should_handle_http_error_responses(): void $this->httpClient->method('get')->willReturn($response); // Act - $result = $this->fetcher->fetch($urlSource, $this->modifiersApplier); + $result = $this->fetcher->fetch(source: $urlSource, modifiersApplier: $this->modifiersApplier); // Assert $this->assertStringContainsString("URL: {$url}", $result); @@ -252,7 +252,7 @@ public function it_should_handle_exceptions_during_http_request(): void // HTTP client mocks - throw exception $this->httpClient ->method('get') - ->willThrowException(new \RuntimeException($exceptionMessage)); + ->willThrowException(new \RuntimeException(message: $exceptionMessage)); // Log the error $this->logger @@ -266,7 +266,7 @@ public function it_should_handle_exceptions_during_http_request(): void ); // Act - $result = $this->fetcher->fetch($urlSource, $this->modifiersApplier); + $result = $this->fetcher->fetch(source: $urlSource, modifiersApplier: $this->modifiersApplier); // Assert $this->assertStringContainsString("URL: {$url}", $result); @@ -301,22 +301,22 @@ public function it_should_process_multiple_urls(): void $this->modifiersApplier->method('apply')->willReturn('Modified content'); // Act - $result = $this->fetcher->fetch($urlSource, $this->modifiersApplier); + $result = $this->fetcher->fetch(source: $urlSource, modifiersApplier: $this->modifiersApplier); // Assert $this->assertStringContainsString("URL: https://example.com", $result); $this->assertStringContainsString("URL: https://example.org", $result); $this->assertStringContainsString("Modified content", $result); // Check if each URL appears twice (once in URL comment, once in END OF URL comment) - $this->assertEquals(2, \substr_count($result, "https://example.com")); - $this->assertEquals(2, \substr_count($result, "https://example.org")); + $this->assertEquals(2, \substr_count(haystack: $result, needle: "https://example.com")); + $this->assertEquals(2, \substr_count(haystack: $result, needle: "https://example.org")); } protected function setUp(): void { $this->httpClient = $this->createMock(HttpClientInterface::class); $this->variableResolver = new VariableResolver( - new VariableReplacementProcessor(), + processor: new VariableReplacementProcessor(), ); $this->cleaner = $this->createMock(HtmlCleanerInterface::class); $this->selectorExtractor = $this->createMock(SelectorContentExtractorInterface::class); diff --git a/tests/src/Unit/Source/Url/UrlSourceTest.php b/tests/src/Unit/Source/Url/UrlSourceTest.php index b13f92a7..044817ee 100644 --- a/tests/src/Unit/Source/Url/UrlSourceTest.php +++ b/tests/src/Unit/Source/Url/UrlSourceTest.php @@ -50,7 +50,7 @@ public static function provideSelectorData(): array #[Test] public function it_should_create_url_source_with_required_parameters(): void { - $source = new UrlSource(self::SAMPLE_URLS); + $source = new UrlSource(urls: self::SAMPLE_URLS); $this->assertSame(self::SAMPLE_URLS, $source->urls); $this->assertEmpty($source->getDescription()); @@ -88,7 +88,7 @@ public function it_should_create_from_valid_array(): void 'tags' => self::SAMPLE_TAGS, ]; - $source = $this->factory->create($data); + $source = $this->factory->create(config: $data); $this->assertSame(self::SAMPLE_URLS, $source->urls); $this->assertSame(self::SAMPLE_DESCRIPTION, $source->getDescription()); @@ -104,7 +104,7 @@ public function it_should_create_from_minimal_array(): void 'urls' => self::SAMPLE_URLS, ]; - $source = $this->factory->create($data); + $source = $this->factory->create(config: $data); $this->assertSame(self::SAMPLE_URLS, $source->urls); $this->assertEmpty($source->getDescription()); @@ -118,7 +118,7 @@ public function it_should_throw_exception_for_missing_urls(): void { $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('URL source must have a "urls" array property'); - $this->factory->create([ + $this->factory->create(config: [ 'description' => self::SAMPLE_DESCRIPTION, ]); } @@ -129,7 +129,7 @@ public function it_should_throw_exception_for_invalid_urls_type(): void $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('URL source must have a "urls" array property'); - $this->factory->create([ + $this->factory->create(config: [ 'urls' => 'not an array', ]); } @@ -191,6 +191,6 @@ protected function setUp(): void { parent::setUp(); - $this->factory = new UrlSourceFactory($this->createDirectories()); + $this->factory = new UrlSourceFactory(dirs: $this->createDirectories()); } }