Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
44 / 44
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
AgentsCommand
100.00% covered (success)
100.00%
44 / 44
100.00% covered (success)
100.00%
3 / 3
6
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 configure
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 execute
100.00% covered (success)
100.00%
38 / 38
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3declare(strict_types=1);
4
5/**
6 * Fast Forward Development Tools for PHP projects.
7 *
8 * This file is part of fast-forward/dev-tools project.
9 *
10 * @author   Felipe SayĆ£o Lobato Abreu <github@mentordosnerds.com>
11 * @license  https://opensource.org/licenses/MIT MIT License
12 *
13 * @see      https://github.com/php-fast-forward/
14 * @see      https://github.com/php-fast-forward/dev-tools
15 * @see      https://github.com/php-fast-forward/dev-tools/issues
16 * @see      https://php-fast-forward.github.io/dev-tools/
17 * @see      https://datatracker.ietf.org/doc/html/rfc2119
18 */
19
20namespace FastForward\DevTools\Console\Command;
21
22use FastForward\DevTools\Console\Command\Traits\LogsCommandResults;
23use FastForward\DevTools\Console\Input\HasJsonOption;
24use FastForward\DevTools\Filesystem\FilesystemInterface;
25use FastForward\DevTools\Path\DevToolsPathResolver;
26use FastForward\DevTools\Sync\PackagedDirectorySynchronizer;
27use Psr\Log\LoggerInterface;
28use Symfony\Component\Console\Attribute\AsCommand;
29use Symfony\Component\Console\Command\Command;
30use Symfony\Component\Console\Input\InputInterface;
31use Symfony\Component\Console\Output\OutputInterface;
32
33/**
34 * Synchronizes packaged Fast Forward project agents into the consumer repository.
35 */
36#[AsCommand(
37    name: 'agents:agents',
38    description: 'Synchronizes Fast Forward project agents into .agents/agents directory.',
39    aliases: ['agents'],
40)]
41 class AgentsCommand extends Command
42{
43    use HasJsonOption;
44    use LogsCommandResults;
45
46    private const string AGENTS_DIRECTORY = '.agents/agents';
47
48    /**
49     * @param PackagedDirectorySynchronizer $synchronizer
50     * @param FilesystemInterface $filesystem
51     * @param LoggerInterface $logger
52     */
53    public function __construct(
54        private  PackagedDirectorySynchronizer $synchronizer,
55        private  FilesystemInterface $filesystem,
56        private  LoggerInterface $logger,
57    ) {
58        parent::__construct();
59    }
60
61    /**
62     * Configures JSON output options for the synchronization command.
63     */
64    protected function configure(): void
65    {
66        $this->setHelp(
67            'This command ensures the consumer repository contains linked Fast Forward project agents by creating'
68            . ' symlinks to the packaged prompts and removing broken links.'
69        );
70        $this->addJsonOption();
71    }
72
73    /**
74     * @param InputInterface $input
75     * @param OutputInterface $output
76     *
77     * @return int
78     */
79    protected function execute(InputInterface $input, OutputInterface $output): int
80    {
81        $packageAgentsPath = DevToolsPathResolver::getPackagePath(self::AGENTS_DIRECTORY);
82        $agentsDir = $this->filesystem->getAbsolutePath(self::AGENTS_DIRECTORY);
83        $this->logger->info('Starting agents synchronization...');
84
85        if (! $this->filesystem->exists($packageAgentsPath)) {
86            return $this->failure(
87                'No packaged .agents/agents found at: {packaged_agents_path}',
88                $input,
89                [
90                    'packaged_agents_path' => $packageAgentsPath,
91                    'agents_dir' => $agentsDir,
92                    'directory_created' => false,
93                ],
94            );
95        }
96
97        $directoryCreated = false;
98
99        if (! $this->filesystem->exists($agentsDir)) {
100            $this->filesystem->mkdir($agentsDir);
101            $directoryCreated = true;
102            $this->logger->info('Created .agents/agents directory.');
103        }
104
105        $result = $this->synchronizer->synchronize($agentsDir, $packageAgentsPath, self::AGENTS_DIRECTORY);
106
107        if ($result->failed()) {
108            return $this->failure(
109                'Agents synchronization failed.',
110                $input,
111                [
112                    'packaged_agents_path' => $packageAgentsPath,
113                    'agents_dir' => $agentsDir,
114                    'directory_created' => $directoryCreated,
115                ],
116            );
117        }
118
119        return $this->success(
120            'Agents synchronization completed successfully.',
121            $input,
122            [
123                'packaged_agents_path' => $packageAgentsPath,
124                'agents_dir' => $agentsDir,
125                'directory_created' => $directoryCreated,
126            ],
127        );
128    }
129}