Skip to content

Commit 9efb3ee

Browse files
committed
feat(): Beautify prompts
1 parent d459453 commit 9efb3ee

File tree

9 files changed

+182
-157
lines changed

9 files changed

+182
-157
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"require": {
2424
"php": ">=8.0",
2525
"ext-json": "*",
26-
"artemeon/console": "^0.3.0",
26+
"artemeon/console": "^0.4.0",
2727
"guzzlehttp/guzzle": "^7.3.0",
2828
"symfony/console": "^5.0|^6.0",
2929
"symfony/yaml": "^5.0|^6.0",

src/Command/CheckUpdateCommand.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ public function __invoke(): int
2929
$name = VersionHelper::getPackageName();
3030

3131
if ($updateAvailable) {
32-
render(<<<HTML
32+
render(
33+
<<<HTML
3334
<table>
3435
<thead>
3536
<tr>
@@ -42,7 +43,8 @@ public function __invoke(): int
4243
</tr>
4344
</tbody>
4445
</table>
45-
HTML);
46+
HTML
47+
);
4648
}
4749

4850
return self::SUCCESS;

src/Command/Command.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44

55
namespace Artemeon\M2G\Command;
66

7+
use Artemeon\Console\Command as BaseCommand;
78
use Artemeon\M2G\Config\ConfigReader;
89

9-
class Command extends \Artemeon\Console\Command
10+
class Command extends BaseCommand
1011
{
11-
final protected function header(): void
12+
final public function header(): void
1213
{
1314
$this->output->write(
1415
'
@@ -18,12 +19,11 @@ final protected function header(): void
1819
| | | || (_| || | | || |_ | |\__ \ <comment>/ __/</comment> | |_| || || |_ | _ || |_| || |_) |
1920
|_| |_| \__,_||_| |_| \__||_||___/ <comment>|_____|</comment> \____||_| \__||_| |_| \__,_||_.__/
2021
21-
2222
'
2323
);
2424
}
2525

26-
final protected function checkConfig(): void
26+
final public function checkConfig(): void
2727
{
2828
$config = (new ConfigReader())->read();
2929

src/Command/ConfigurationCommand.php

Lines changed: 55 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ public function __invoke(): int
3131
$this->warn('Configuration file already exists');
3232
$this->warn('If you continue your configuration will be overwritten');
3333

34-
if (!$this->confirm("\n Are you sure you want to continue?")) {
35-
$this->info("\n Alright!\n");
34+
if (!$this->confirm('Are you sure you want to continue?')) {
35+
$this->info('Alright!');
3636

3737
return self::INVALID;
3838
}
@@ -53,74 +53,77 @@ public function __invoke(): int
5353

5454
private function askForMantisUrl(): void
5555
{
56-
$mantisUrl = $this->ask('Please enter the URL of your Mantis installation (e.g. https://tickets.company.tld):');
56+
$mantisUrl = $this->ask(
57+
label: 'The URL of your Mantis installation',
58+
placeholder: 'E.g. https://tickets.company.tld/',
59+
required: true,
60+
validate: function ($value) {
61+
$parsedUrl = parse_url($value);
62+
63+
if ($parsedUrl === false) {
64+
return 'You must enter a valid URL.';
65+
}
66+
67+
if (!isset($parsedUrl['scheme'])) {
68+
return 'The URL must include a scheme like "http://" or "https://".';
69+
}
70+
71+
if (!isset($parsedUrl['host'])) {
72+
return 'The URL must include a valid host.';
73+
}
74+
75+
$port = isset($parsedUrl['port']) ? ':' . $parsedUrl['port'] : '';
76+
$mantisUrl = "{$parsedUrl['scheme']}://{$parsedUrl['host']}$port/";
77+
78+
$headers = @get_headers($mantisUrl);
79+
if (!$headers || $headers[0] === 'HTTP/1.1 404 Not Found') {
80+
return 'The given URL is unreachable. If this error persists, please check your internet connection.';
81+
}
82+
83+
return null;
84+
},
85+
);
5786

5887
$parsedUrl = parse_url($mantisUrl);
59-
60-
if ($parsedUrl === false || !isset($parsedUrl['scheme']) || !isset($parsedUrl['host'])) {
61-
$this->error("The URL you entered is invalid.");
62-
63-
$this->askForMantisUrl();
64-
}
65-
6688
$port = isset($parsedUrl['port']) ? ':' . $parsedUrl['port'] : '';
67-
6889
$mantisUrl = "{$parsedUrl['scheme']}://{$parsedUrl['host']}$port/";
6990

70-
// Check if something is available on the given URL
71-
// If not, we assume that the URL is wrong.
72-
$headers = @get_headers($mantisUrl);
73-
if (!$headers || $headers[0] === 'HTTP/1.1 404 Not Found') {
74-
$this->error(
75-
"The given URL is unreachable. If this error persists, please check your internet connection."
76-
);
77-
78-
$this->askForMantisUrl();
79-
}
80-
8191
$this->config['mantisUrl'] = $mantisUrl;
8292
}
8393

8494
private function askForMantisToken(): void
8595
{
8696
$this->info("Head over to {$this->config['mantisUrl']}api_tokens_page.php and create a new API token.");
87-
$token = $this->secret('Mantis API Token');
88-
89-
if (empty($token)) {
90-
$this->error('The token is empty. Please try again.');
91-
92-
$this->askForMantisToken();
93-
}
9497

95-
$this->config['mantisToken'] = $token;
98+
$this->config['mantisToken'] = $this->password(
99+
label: 'Mantis API Token',
100+
required: true,
101+
);
96102
}
97103

98104
private function askForGitHubToken(): void
99105
{
100-
$this->info("Head over to https://github.com/settings/tokens, create a new personal access token with the `repo` scope.");
101-
102-
$token = $this->secret("GitHub Token");
103-
104-
if (empty($token)) {
105-
$this->error('The token is empty. Please try again.');
106-
107-
$this->askForGitHubToken();
108-
}
109-
110-
$this->config['githubToken'] = $token;
106+
$this->info('Head over to https://github.com/settings/tokens, create a new personal access token with the `repo` scope.');
107+
108+
$this->config['githubToken'] = $this->password(
109+
label: 'GitHub Personal Access Token',
110+
required: true,
111+
validate: fn ($value) => !str_starts_with($value, 'ghp_') && str_starts_with($value, 'github_pat_')
112+
? 'The provided value is not a valid GitHub PAT.'
113+
: null,
114+
);
111115
}
112116

113117
private function askForGitHubRepository(): void
114118
{
115-
$repository = $this->ask('Enter the GitHub repository you want to create issues for (e.g. user/repository)');
116-
117-
if (empty($repository) || count(explode('/', $repository)) !== 2) {
118-
$this->error("The given repository is invalid.");
119-
120-
$this->askForGitHubRepository();
121-
}
122-
123-
$this->config['githubRepository'] = $repository;
119+
$this->config['githubRepository'] = $this->ask(
120+
label: 'GitHub Repository(e.g. user/repository)',
121+
placeholder: 'E.g. user/repository',
122+
required: true,
123+
validate: fn ($value) => count(explode('/', $value)) !== 2
124+
? 'Invalid repository name.'
125+
: null,
126+
);
124127
}
125128

126129
private function saveConfig(): void
@@ -135,13 +138,13 @@ private function saveConfig(): void
135138

136139
render(
137140
<<<HTML
138-
<div class="my-1 ml-1 px-1 bg-green-500 text-gray-900">
141+
<div class="mb-1 ml-2 px-1 bg-green-500 text-gray-900">
139142
<strong>🚀 Ready for liftoff! 🚀</strong>
140143
</div>
141144
HTML
142145
);
143146

144-
$this->success(" Synchronize your first issue by running `mantis2github sync`!\n");
147+
$this->success('Synchronize your first issue by running `mantis2github sync`!');
145148
}
146149

147150
private function readExistingConfigFromPath(): void

src/Command/CreateGithubIssueFromMantisIssue.php

Lines changed: 55 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
class CreateGithubIssueFromMantisIssue extends Command
1515
{
16-
protected string $signature = 'sync {ids* : Mantis issue ids}';
16+
protected string $signature = 'sync {ids* : Mantis issue IDs}';
1717

1818
protected ?string $description = 'Synchronize a list of Mantis issues to GitHub';
1919

@@ -37,74 +37,70 @@ public function __invoke(): int
3737
$this->title('Mantis 2 GitHub Sync');
3838

3939
$ids = array_unique($this->argument('ids'));
40+
$message = count($ids) !== 1 ? 'Creating issues ...' : 'Creating issue ...';
4041

4142
$this->newLine();
4243

43-
$progressBar = new ProgressBar($this->output, count($ids));
44-
$progressBar->start();
45-
46-
$labels = array_map(static fn ($label) => $label['name'], $this->githubConnector->getLabels());
47-
4844
$issues = [];
4945

50-
foreach ($ids as $id) {
51-
$mantisIssue = $this->mantisConnector->readIssue((int)$id);
52-
53-
if ($mantisIssue === null) {
54-
$issues[] = [
55-
'id' => $id,
56-
'icon' => '<error>✕</error>',
57-
'message' => '<error>Mantis issue not found.</error>',
58-
'issue' => '',
59-
];
60-
continue;
61-
}
62-
63-
$newGithubIssue = GithubIssue::fromMantisIssue($mantisIssue);
64-
65-
$filteredLabels = array_values(
66-
array_filter($labels, static fn ($label) => strtolower($label) === strtolower($mantisIssue->getProject())),
67-
);
68-
69-
$newGithubIssue->setLabels($filteredLabels);
70-
$newGithubIssue = $this->githubConnector->createIssue($newGithubIssue);
46+
$this->spin(function () use ($ids) {
47+
$labels = array_map(static fn ($label) => $label['name'], $this->githubConnector->getLabels());
48+
49+
foreach ($ids as $id) {
50+
$mantisIssue = $this->mantisConnector->readIssue((int)$id);
51+
52+
if ($mantisIssue === null) {
53+
$issues[] = [
54+
'id' => $id,
55+
'icon' => '<error>✕</error>',
56+
'message' => '<error>Mantis issue not found.</error>',
57+
'issue' => '',
58+
];
59+
continue;
60+
}
61+
62+
$newGithubIssue = GithubIssue::fromMantisIssue($mantisIssue);
63+
64+
$filteredLabels = array_values(
65+
array_filter($labels, static fn ($label) => strtolower($label) === strtolower($mantisIssue->getProject())),
66+
);
67+
68+
$newGithubIssue->setLabels($filteredLabels);
69+
$newGithubIssue = $this->githubConnector->createIssue($newGithubIssue);
70+
71+
if ($newGithubIssue === null) {
72+
$issues[] = [
73+
'id' => $id,
74+
'icon' => '<error>✕</error>',
75+
'message' => '<error>GitHub issue could not be created.</error>',
76+
'issue' => '',
77+
];
78+
continue;
79+
}
80+
81+
$mantisIssue->setUpstreamTicket(
82+
trim($mantisIssue->getUpstreamTicket() . ' ' . $newGithubIssue->getIssueUrl())
83+
);
84+
$patched = $this->mantisConnector->patchUpstreamField($mantisIssue);
85+
86+
if ($patched === false) {
87+
$issues[] = [
88+
'id' => $id,
89+
'icon' => '<error>✕</error>',
90+
'message' => '<error>Upstream ticket URL could not be updated.</error>',
91+
'issue' => '',
92+
];
93+
continue;
94+
}
7195

72-
if ($newGithubIssue === null) {
7396
$issues[] = [
7497
'id' => $id,
75-
'icon' => '<error>✕</error>',
76-
'message' => '<error>GitHub issue could not be created.</error>',
77-
'issue' => '',
98+
'icon' => '<info>✓</info>',
99+
'message' => '<info>Mantis issue has been synchronized.</info>',
100+
'issue' => $newGithubIssue->getIssueUrl(),
78101
];
79-
continue;
80102
}
81-
82-
$mantisIssue->setUpstreamTicket(
83-
trim($mantisIssue->getUpstreamTicket() . ' ' . $newGithubIssue->getIssueUrl())
84-
);
85-
$patched = $this->mantisConnector->patchUpstreamField($mantisIssue);
86-
87-
if ($patched === false) {
88-
$issues[] = [
89-
'id' => $id,
90-
'icon' => '<error>✕</error>',
91-
'message' => '<error>Upstream ticket URL could not be updated.</error>',
92-
'issue' => '',
93-
];
94-
continue;
95-
}
96-
97-
$issues[] = [
98-
'id' => $id,
99-
'icon' => '<info>✓</info>',
100-
'message' => '<info>Mantis issue has been synchronized.</info>',
101-
'issue' => $newGithubIssue->getIssueUrl(),
102-
];
103-
104-
$progressBar->advance();
105-
}
106-
107-
$progressBar->finish();
103+
}, $message);
108104

109105
$this->newLine();
110106

0 commit comments

Comments
 (0)