Skip to content

Commit a0d1032

Browse files
committed
🐛 Fixed bug where autoload.php was not being found correctly
♻️ Refactored ProcessDirectory and ProcessFile classes 🔧 Added bin entry to composer.json ✨ Added readme with installation instructions and usage examples
1 parent 9574ebd commit a0d1032

File tree

7 files changed

+191
-44
lines changed

7 files changed

+191
-44
lines changed

bin/aiphpdocs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
if (file_exists(__DIR__.'/../../../autoload.php')) {
5+
require __DIR__.'/../../../autoload.php';
6+
} else {
7+
require __DIR__.'/../vendor/autoload.php';
8+
}
9+
10+
use Molbal\AiPhpdoc\ProcessDirectory;
11+
use Molbal\AiPhpdoc\ProcessFile;
12+
use Symfony\Component\Console\Application;
13+
14+
$application = new Application('AI-PHPDocs by molbal', '1.0.0');
15+
16+
$application->add(new ProcessFile());
17+
$application->add(new ProcessDirectory());
18+
19+
$application->run();
20+

bin/aiphpdocs.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
<?php
22
require __DIR__.'/../vendor/autoload.php';
33

4-
use Molbal\AiPhpdoc\InsertMissingDocs;
4+
use Molbal\AiPhpdoc\ProcessDirectory;
5+
use Molbal\AiPhpdoc\ProcessFile;
56
use Symfony\Component\Console\Application;
67

7-
$application = new Application();
8+
$application = new Application('AI-PHPDocs by molbal', '1.0.0');
89

9-
10-
$application->add(new InsertMissingDocs());
11-
// ... register commands
10+
$application->add(new ProcessFile());
11+
$application->add(new ProcessDirectory());
1212

1313
$application->run();
1414

composer.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,8 @@
1919
"php": "^8.1",
2020
"symfony/console": "^6.2",
2121
"openai-php/client": "^0.3.0"
22-
}
22+
},
23+
"bin": [
24+
"bin/aiphpdocs"
25+
]
2326
}

readme.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# AI PHPDocs
2+
3+
AI PHPDocs is a tool that uses GPT-3 to automatically add missing PHPDoc comments to your PHP code.
4+
5+
## Prerequisites
6+
7+
Before using AI PHPDocs, you will need to have an OpenAI API key set as an environment variable.
8+
9+
```shell
10+
export OPENAI_KEY=...
11+
```
12+
13+
## Installation
14+
15+
To install AI PHPDocs, run the following command:
16+
17+
18+
```shell
19+
composer global require molbal/ai-phpdocs
20+
```
21+
22+
## Usage
23+
24+
To add missing PHPDoc comments to a single file, use the following command:
25+
26+
```shell
27+
aiphpdocs file /path/to/file.php
28+
```
29+
30+
To add missing PHPDoc comments to a directory of files, use the following command. By default it iterates through the current directory for all files, but does not go into subdirectories:
31+
32+
```shell
33+
aiphpdocs directory
34+
```
35+
36+
37+
You may set the `--recursive` flag, or `-r` for short for it to go into subdirectories.
38+
39+
If you pass another variable (regardless of the recursive flag) it will treat it as another directory to sweep through instead of the working directory.
40+
41+
```shell
42+
aiphpdocs directory --r /somewhere/else
43+
```
44+
45+
## License
46+
47+
AI PHPDocs is licensed under the AGPL-3.0 license. See LICENSE for more information.

src/ProcessDirectory.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Molbal\AiPhpdoc;
4+
5+
use Symfony\Component\Console\Command\Command;
6+
use Symfony\Component\Console\Input\InputArgument;
7+
use Symfony\Component\Console\Input\InputInterface;
8+
use Symfony\Component\Console\Input\InputOption;
9+
use Symfony\Component\Console\Output\OutputInterface;
10+
11+
class ProcessDirectory extends Command
12+
{
13+
14+
protected function configure()
15+
{
16+
$this
17+
->setName('directory')
18+
->setDescription('Adds missing PHPDoc blocks to functions in a directory')
19+
->addArgument('directory', InputArgument::OPTIONAL, 'The directory to iterate through. Defaults to `.`')
20+
->addOption('recursive', 'r', InputOption::VALUE_NONE,'Iterate recusrively? Defaults to no');
21+
}
22+
23+
24+
/**
25+
* Execute the function
26+
*
27+
* @param InputInterface $input
28+
* @param OutputInterface $output
29+
* @return int
30+
*/
31+
protected function execute(InputInterface $input, OutputInterface $output)
32+
{
33+
$dirPath = $input->getArgument('file');
34+
$recursive = $input->getOption('recursive') !== false;
35+
return (new ProcessFacade())->processDirectory($dirPath, $recursive, $output);
36+
}
37+
}

src/InsertMissingDocs.php renamed to src/ProcessFacade.php

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,66 +2,39 @@
22

33
namespace Molbal\AiPhpdoc;
44

5-
use Symfony\Component\Console\Attribute\AsCommand;
65
use Symfony\Component\Console\Command\Command;
7-
use Symfony\Component\Console\Input\InputArgument;
8-
use Symfony\Component\Console\Input\InputInterface;
96
use Symfony\Component\Console\Output\OutputInterface;
107

11-
#[AsCommand(
12-
name: 'aiphpdocs:generate',
13-
description: 'Inserts missing PHPDoc blocks in a file.',
14-
aliases: [],
15-
hidden: false
16-
)]
17-
class InsertMissingDocs extends Command
8+
class ProcessFacade
189
{
19-
20-
21-
/**
22-
* Configures the current command.
23-
*
24-
* @param string $file The file to list the functions of
25-
*/
26-
protected function configure()
27-
{
28-
$this->addArgument('file', InputArgument::REQUIRED, 'The file to list the functions of');
29-
}
30-
31-
3210
/**
33-
* Execute the function
34-
*
35-
* @param InputInterface $input
11+
* @param mixed $filePath
3612
* @param OutputInterface $output
3713
* @return int
3814
*/
39-
protected function execute(InputInterface $input, OutputInterface $output)
15+
public function processFile(mixed $filePath, OutputInterface $output): int
4016
{
41-
$filePath = $input->getArgument('file');
4217
try {
4318
$functions = FileParser::getFunctionsFromFile($filePath);
4419
$errors = 0;
4520
$completions = 0;
4621
foreach ($functions as $function) {
4722
if (!$function['phpdoc']) {
48-
$output->writeln('Found function without docblock: '.$function['name'].'');
23+
$output->writeln('Found function without docblock: ' . $function['name'] . '');
4924
try {
5025
$docs = DocumentationGenerator::createDocBlock($function['body']);
5126
if (FileWriter::writeDocBlock($filePath, $function['body'], $docs)) {
52-
$output->writeln('<info>Wrote docblock for '.$function['name'].'</info>');
27+
$output->writeln('<info>Wrote docblock for ' . $function['name'] . '</info>');
5328
$completions++;
54-
}
55-
else {
29+
} else {
5630
if (FileWriter::writeDocBlock($filePath, $function['body'], $docs)) {
57-
$output->writeln('<error>Generated docblock for '.$function['name'].', but could not write it to the file.</error>');
31+
$output->writeln('<error>Generated docblock for ' . $function['name'] . ', but could not write it to the file.</error>');
5832
$output->writeln($docs);
5933
$errors++;
6034
}
6135
}
62-
}
63-
catch (\Exception $error) {
64-
$output->writeln('<error>Could not generate docblock for '.$function['name'].': '.$error->getMessage().'</error>');
36+
} catch (\Exception $error) {
37+
$output->writeln('<error>Could not generate docblock for ' . $function['name'] . ': ' . $error->getMessage() . '</error>');
6538
}
6639
}
6740
}
@@ -71,7 +44,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
7144
}
7245

7346
if ($completions > 0) {
74-
$output->writeln('Finished processing '.$filePath.' with '.$completions.' docblocks written and '.$errors.' errors.');
47+
$output->writeln('Finished processing ' . $filePath . ' with ' . $completions . ' docblocks written and ' . $errors . ' errors.');
7548
}
7649

7750
return $errors > 0 ? Command::FAILURE : Command::SUCCESS;
@@ -80,4 +53,31 @@ protected function execute(InputInterface $input, OutputInterface $output)
8053
return Command::FAILURE;
8154
}
8255
}
83-
}
56+
57+
public function processDirectory(string $directoryPath, bool $recursive, OutputInterface $output): int
58+
{
59+
$output->writeln('<comment>Processing directory: '.$directoryPath.'</comment>');
60+
$success = Command::SUCCESS;
61+
62+
if (!is_dir($directoryPath)) {
63+
$output->writeln('<error>'.$directoryPath.' is not a valid directory.</error>');
64+
return Command::INVALID;
65+
}
66+
67+
$iterator = new \RecursiveDirectoryIterator($directoryPath, \RecursiveDirectoryIterator::SKIP_DOTS);
68+
69+
70+
foreach ($iterator as $file) {
71+
if ($file->isFile() && $file->getExtension() == 'php') {
72+
$success = $this->processFile($file->getPathname(), $output) == Command::SUCCESS ? Command::SUCCESS : Command::FAILURE;
73+
}
74+
75+
if ($file->isDir() && $recursive ) {
76+
$this->processDirectory($file->getPathname(), $recursive, $output);
77+
}
78+
}
79+
80+
return $success;
81+
}
82+
83+
}

src/ProcessFile.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Molbal\AiPhpdoc;
4+
5+
use Symfony\Component\Console\Attribute\AsCommand;
6+
use Symfony\Component\Console\Command\Command;
7+
use Symfony\Component\Console\Input\InputArgument;
8+
use Symfony\Component\Console\Input\InputInterface;
9+
use Symfony\Component\Console\Output\OutputInterface;
10+
11+
class ProcessFile extends Command
12+
{
13+
14+
/**
15+
* Configures the current command.
16+
*
17+
* @param string $file The file to list the functions of
18+
*/
19+
protected function configure()
20+
{
21+
$this
22+
->setName('file')
23+
->setDescription('Adds missing PHPDoc blocks to functions in a file')
24+
->addArgument('file', InputArgument::REQUIRED, 'The file to process.');
25+
}
26+
27+
28+
/**
29+
* Execute the function
30+
*
31+
* @param InputInterface $input
32+
* @param OutputInterface $output
33+
* @return int
34+
*/
35+
protected function execute(InputInterface $input, OutputInterface $output)
36+
{
37+
$filePath = $input->getArgument('file');
38+
return (new ProcessFacade())->processFile($filePath, $output);
39+
}
40+
}

0 commit comments

Comments
 (0)