Skip to content

Commit 908939f

Browse files
committed
✨ feat: implement ThemeSelectionService for theme management
1 parent bf018e2 commit 908939f

2 files changed

Lines changed: 159 additions & 121 deletions

File tree

src/Console/Command/Hyva/TokensCommand.php

Lines changed: 7 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,10 @@
44

55
namespace OpenForgeProject\MageForge\Console\Command\Hyva;
66

7-
use Laravel\Prompts\SelectPrompt;
87
use OpenForgeProject\MageForge\Console\Command\AbstractCommand;
9-
use OpenForgeProject\MageForge\Model\ThemeList;
10-
use OpenForgeProject\MageForge\Model\ThemePath;
11-
use OpenForgeProject\MageForge\Service\EnvironmentService;
128
use OpenForgeProject\MageForge\Service\HyvaTokens\ConfigReader;
139
use OpenForgeProject\MageForge\Service\HyvaTokens\TokenProcessor;
14-
use OpenForgeProject\MageForge\Service\ThemeBuilder\HyvaThemes\Builder as HyvaBuilder;
10+
use OpenForgeProject\MageForge\Service\ThemeSelectionService;
1511
use Symfony\Component\Console\Command\Command;
1612
use Symfony\Component\Console\Input\InputArgument;
1713
use Symfony\Component\Console\Input\InputInterface;
@@ -23,20 +19,14 @@
2319
class TokensCommand extends AbstractCommand
2420
{
2521
/**
26-
* @param ThemePath $themePath
27-
* @param ThemeList $themeList
22+
* @param ThemeSelectionService $themeSelectionService
2823
* @param TokenProcessor $tokenProcessor
29-
* @param HyvaBuilder $hyvaBuilder
3024
* @param ConfigReader $configReader
31-
* @param EnvironmentService $environmentService
3225
*/
3326
public function __construct(
34-
private readonly ThemePath $themePath,
35-
private readonly ThemeList $themeList,
27+
private readonly ThemeSelectionService $themeSelectionService,
3628
private readonly TokenProcessor $tokenProcessor,
37-
private readonly HyvaBuilder $hyvaBuilder,
3829
private readonly ConfigReader $configReader,
39-
private readonly EnvironmentService $environmentService,
4030
) {
4131
parent::__construct();
4232
}
@@ -64,7 +54,7 @@ protected function executeCommand(InputInterface $input, OutputInterface $output
6454

6555
// If no theme code provided, select interactively
6656
if (empty($themeCode)) {
67-
$themeCode = $this->selectThemeInteractively($output);
57+
$themeCode = $this->themeSelectionService->selectHyvaTheme($this->io);
6858
if ($themeCode === null) {
6959
return Command::FAILURE;
7060
}
@@ -80,84 +70,6 @@ protected function executeCommand(InputInterface $input, OutputInterface $output
8070
return $this->processTokens($themeCode, $themePath);
8171
}
8272

83-
/**
84-
* Select theme interactively
85-
*
86-
* @param OutputInterface $output
87-
* @return string|null
88-
*/
89-
private function selectThemeInteractively(OutputInterface $output): ?string
90-
{
91-
$hyvaThemes = $this->getHyvaThemes();
92-
93-
if (empty($hyvaThemes)) {
94-
$this->io->error('No Hyvä themes found in this installation.');
95-
return null;
96-
}
97-
98-
// Check if we're in an interactive terminal environment
99-
if (!$this->environmentService->isInteractiveTerminal()) {
100-
$this->displayAvailableThemes($hyvaThemes);
101-
return null;
102-
}
103-
104-
return $this->promptForTheme($hyvaThemes);
105-
}
106-
107-
/**
108-
* Display available themes for non-interactive environments
109-
*
110-
* @param array $hyvaThemes
111-
* @return void
112-
*/
113-
private function displayAvailableThemes(array $hyvaThemes): void
114-
{
115-
$this->io->info('Available Hyvä themes:');
116-
foreach ($hyvaThemes as $theme) {
117-
$this->io->writeln(' - ' . $theme->getCode());
118-
}
119-
$this->io->newLine();
120-
$this->io->info('Usage: bin/magento mageforge:hyva:tokens <theme-code>');
121-
}
122-
123-
/**
124-
* Prompt user to select a theme
125-
*
126-
* @param array $hyvaThemes
127-
* @return string|null
128-
*/
129-
private function promptForTheme(array $hyvaThemes): ?string
130-
{
131-
$options = [];
132-
foreach ($hyvaThemes as $theme) {
133-
$options[] = $theme->getCode();
134-
}
135-
136-
// Set environment variables for Laravel Prompts
137-
$this->environmentService->setPromptEnvironment();
138-
139-
$themeCodePrompt = new SelectPrompt(
140-
label: 'Select Hyvä theme to generate tokens for',
141-
options: $options,
142-
hint: 'Arrow keys to navigate, Enter to confirm'
143-
);
144-
145-
try {
146-
$selectedTheme = $themeCodePrompt->prompt();
147-
\Laravel\Prompts\Prompt::terminal()->restoreTty();
148-
149-
// Reset environment
150-
$this->environmentService->resetPromptEnvironment();
151-
152-
return $selectedTheme;
153-
} catch (\Exception $e) {
154-
// Reset environment on exception
155-
$this->environmentService->resetPromptEnvironment();
156-
$this->io->error('Interactive mode failed: ' . $e->getMessage());
157-
return null;
158-
}
159-
}
160-
16173
/**
16274
* Validate theme exists and is a Hyva theme
16375
*
@@ -166,16 +78,10 @@ private function promptForTheme(array $hyvaThemes): ?string
16678
*/
16779
private function validateTheme(string $themeCode): ?string
16880
{
169-
// Get theme path
170-
$themePath = $this->themePath->getPath($themeCode);
81+
// Validate theme
82+
$themePath = $this->themeSelectionService->validateTheme($themeCode, true);
17183
if ($themePath === null) {
172-
$this->io->error("Theme $themeCode is not installed.");
173-
return null;
174-
}
175-
176-
// Verify this is a Hyva theme
177-
if (!$this->hyvaBuilder->detect($themePath)) {
178-
$this->io->error("Theme $themeCode is not a Hyvä theme. This command only works with Hyvä themes.");
84+
$this->io->error("Theme $themeCode is not installed or is not a Hyvä theme.");
17985
return null;
18086
}
18187

@@ -276,24 +182,4 @@ private function handleFailure(array $result): int
276182
JSON);
277183
return Command::FAILURE;
278184
}
279-
280-
/**
281-
* Get list of Hyva themes
282-
*
283-
* @return array
284-
*/
285-
private function getHyvaThemes(): array
286-
{
287-
$allThemes = $this->themeList->getAllThemes();
288-
$hyvaThemes = [];
289-
290-
foreach ($allThemes as $theme) {
291-
$themePath = $this->themePath->getPath($theme->getCode());
292-
if ($themePath && $this->hyvaBuilder->detect($themePath)) {
293-
$hyvaThemes[] = $theme;
294-
}
295-
}
296-
297-
return $hyvaThemes;
298-
}
299185
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenForgeProject\MageForge\Service;
6+
7+
use Laravel\Prompts\SelectPrompt;
8+
use OpenForgeProject\MageForge\Model\ThemeList;
9+
use OpenForgeProject\MageForge\Model\ThemePath;
10+
use OpenForgeProject\MageForge\Service\ThemeBuilder\HyvaThemes\Builder as HyvaBuilder;
11+
use Symfony\Component\Console\Style\SymfonyStyle;
12+
13+
/**
14+
* Service for theme selection and validation
15+
*/
16+
class ThemeSelectionService
17+
{
18+
/**
19+
* @param ThemePath $themePath
20+
* @param ThemeList $themeList
21+
* @param HyvaBuilder $hyvaBuilder
22+
* @param EnvironmentService $environmentService
23+
*/
24+
public function __construct(
25+
private readonly ThemePath $themePath,
26+
private readonly ThemeList $themeList,
27+
private readonly HyvaBuilder $hyvaBuilder,
28+
private readonly EnvironmentService $environmentService,
29+
) {
30+
}
31+
32+
/**
33+
* Get Hyva themes interactively or display available themes
34+
*
35+
* @param SymfonyStyle $io
36+
* @return string|null
37+
*/
38+
public function selectHyvaTheme(SymfonyStyle $io): ?string
39+
{
40+
$hyvaThemes = $this->getHyvaThemes();
41+
42+
if (empty($hyvaThemes)) {
43+
$io->error('No Hyvä themes found in this installation.');
44+
return null;
45+
}
46+
47+
// Check if we're in an interactive terminal environment
48+
if (!$this->environmentService->isInteractiveTerminal()) {
49+
$this->displayAvailableThemes($io, $hyvaThemes);
50+
return null;
51+
}
52+
53+
return $this->promptForTheme($io, $hyvaThemes);
54+
}
55+
56+
/**
57+
* Validate theme exists and optionally check if it's a Hyva theme
58+
*
59+
* @param string $themeCode
60+
* @param bool $requireHyva
61+
* @return string|null
62+
*/
63+
public function validateTheme(string $themeCode, bool $requireHyva = false): ?string
64+
{
65+
$themePath = $this->themePath->getPath($themeCode);
66+
if ($themePath === null) {
67+
return null;
68+
}
69+
70+
if ($requireHyva && !$this->hyvaBuilder->detect($themePath)) {
71+
return null;
72+
}
73+
74+
return $themePath;
75+
}
76+
77+
/**
78+
* Get list of Hyva themes
79+
*
80+
* @return array
81+
*/
82+
private function getHyvaThemes(): array
83+
{
84+
$allThemes = $this->themeList->getAllThemes();
85+
$hyvaThemes = [];
86+
87+
foreach ($allThemes as $theme) {
88+
$themePath = $this->themePath->getPath($theme->getCode());
89+
if ($themePath && $this->hyvaBuilder->detect($themePath)) {
90+
$hyvaThemes[] = $theme;
91+
}
92+
}
93+
94+
return $hyvaThemes;
95+
}
96+
97+
/**
98+
* Display available themes for non-interactive environments
99+
*
100+
* @param SymfonyStyle $io
101+
* @param array $hyvaThemes
102+
* @return void
103+
*/
104+
private function displayAvailableThemes(SymfonyStyle $io, array $hyvaThemes): void
105+
{
106+
$io->info('Available Hyvä themes:');
107+
foreach ($hyvaThemes as $theme) {
108+
$io->writeln(' - ' . $theme->getCode());
109+
}
110+
$io->newLine();
111+
$io->info('Usage: bin/magento mageforge:hyva:tokens <theme-code>');
112+
}
113+
114+
/**
115+
* Prompt user to select a theme
116+
*
117+
* @param SymfonyStyle $io
118+
* @param array $hyvaThemes
119+
* @return string|null
120+
*/
121+
private function promptForTheme(SymfonyStyle $io, array $hyvaThemes): ?string
122+
{
123+
$options = [];
124+
foreach ($hyvaThemes as $theme) {
125+
$options[] = $theme->getCode();
126+
}
127+
128+
// Set environment variables for Laravel Prompts
129+
$this->environmentService->setPromptEnvironment();
130+
131+
$themeCodePrompt = new SelectPrompt(
132+
label: 'Select Hyvä theme to generate tokens for',
133+
options: $options,
134+
hint: 'Arrow keys to navigate, Enter to confirm'
135+
);
136+
137+
try {
138+
$selectedTheme = $themeCodePrompt->prompt();
139+
\Laravel\Prompts\Prompt::terminal()->restoreTty();
140+
141+
// Reset environment
142+
$this->environmentService->resetPromptEnvironment();
143+
144+
return $selectedTheme;
145+
} catch (\Exception $e) {
146+
// Reset environment on exception
147+
$this->environmentService->resetPromptEnvironment();
148+
$io->error('Interactive mode failed: ' . $e->getMessage());
149+
return null;
150+
}
151+
}
152+
}

0 commit comments

Comments
 (0)