Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ bin/magento mageforge:theme:build [<themeCodes>...]

**Implementation Details**:

- `themeCodes` accepts single themes (`Vendor/theme`) or just the vendor name (`Vendor`) to target all themes of a specific vendor.
- If no theme codes are provided, displays an interactive prompt to select themes
- For each selected theme:
1. Resolves the theme path
Expand Down Expand Up @@ -109,11 +110,13 @@ bin/magento mageforge:theme:watch [--theme=THEME]
**Usage**:

```bash
bin/magento mageforge:theme:clean [<themename>]
bin/magento mageforge:theme:clean [<themename>...]
```

**Implementation Details**:

- Can accept multiple themes like `Vendor/theme1 Vendor/theme2`.
- Accepts simply the vendor name `Vendor` to clean all registered themes for a vendor.
- If no theme name is provided:
- In interactive terminals, displays an interactive prompt to select the theme to clean
- In non-interactive environments, prints the list of available themes and exits, requiring an explicit theme name
Expand Down
69 changes: 69 additions & 0 deletions src/Console/Command/AbstractCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Laravel\Prompts\SelectPrompt;
use Magento\Framework\Console\Cli;
use OpenForgeProject\MageForge\Service\ThemeSuggester;
use OpenForgeProject\MageForge\Model\ThemeList;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
Expand Down Expand Up @@ -478,4 +479,72 @@ private function removeSecureEnvironmentValue(string $name): void
unset($this->secureEnvStorage[$name]);
$this->clearEnvironmentCache();
}

/**
* Resolve vendor theme codes (e.g., Vendor to all underlying vendor themes)
*
* @param array<string> $themeCodes
* @param ThemeList $themeList
* @return array<string>
*/
protected function resolveVendorThemes(
array $themeCodes,
ThemeList $themeList
): array {
$resolved = [];
$availableThemes = null;

foreach ($themeCodes as $code) {
// Check if it's explicitly a wildcard OR just a vendor name without a slash
$isExplicitWildcard = \str_ends_with($code, '/*');
$isVendorOnly = !\str_contains($code, '/');

if ($isExplicitWildcard || $isVendorOnly) {
// Lazy-load themes only when needed
if ($availableThemes === null) {
$availableThemes = array_map(
fn($theme) => $theme->getCode(),
$themeList->getAllThemes()
);
}

if ($isExplicitWildcard) {
$prefix = substr($code, 0, -1); // Keeps the trailing slash, e.g. "Vendor/"
} else {
$prefix = $code . '/'; // e.g. "Vendor" -> "Vendor/"
}

$matched = array_filter(
$availableThemes,
fn(string $availableCode) => \str_starts_with($availableCode, $prefix)
);

if (empty($matched)) {
$this->io->warning(sprintf("No themes found for vendor/prefix '%s'", $prefix));

// If they typed just a word and it wasn't a vendor,
// we still add it so standard Magento validation kicks in later.
if ($isVendorOnly) {
$resolved[] = $code;
}
} else {
$this->io->note(sprintf(
"Resolved vendor '%s' to %d theme(s): %s",
$code,
count($matched),
implode(', ', $matched)
));

foreach ($matched as $match) {
$resolved[] = $match;
}
}
} else {
$resolved[] = $code;
}
}

// Return a fresh list without duplicates
return array_values(array_unique($resolved));
}
}
33 changes: 27 additions & 6 deletions src/Console/Command/Theme/BuildCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ protected function configure(): void
->addArgument(
'themeCodes',
InputArgument::IS_ARRAY,
'Theme codes to build (format: Vendor/theme, Vendor/theme 2, ...)',
'Theme codes to build (format: Vendor/theme, Vendor, ...)',
)
->setAliases(['frontend:build']);
}
Expand All @@ -66,6 +66,17 @@ protected function configure(): void
protected function executeCommand(InputInterface $input, OutputInterface $output): int
{
$themeCodes = $input->getArgument('themeCodes');

// Allow wildcards using the AbstractCommand helper
if (!empty($themeCodes)) {
$themeCodes = $this->resolveVendorThemes($themeCodes, $this->themeList);

// If wildcards matched nothing and no other explicit themes remain
if (empty($themeCodes)) {
return Command::SUCCESS;
}
}

$isVerbose = $this->isVerbose($output);

if (empty($themeCodes)) {
Expand Down Expand Up @@ -337,12 +348,22 @@ private function processTheme(
private function displayBuildSummary(SymfonyStyle $io, array $successList, float $duration): void
{
$io->newLine();
$io->success(sprintf('🚀 Build process completed in %.2f seconds with the following results:', $duration));
$io->writeln('Summary:');
$io->newLine();

if (empty($successList)) {
$io->warning('No themes were built successfully.');
$successCount = count($successList);

if ($successCount > 0) {
$io->success(sprintf(
'🚀 Successfully built %d theme(s). Build process completed in %.2f seconds.',
$successCount,
$duration
));
$io->writeln('Summary:');
$io->newLine();
} else {
$io->warning(sprintf(
'Build process completed in %.2f seconds, but no themes were built successfully.',
$duration
));
return;
}

Expand Down
11 changes: 10 additions & 1 deletion src/Console/Command/Theme/CleanCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ protected function configure(): void
->addArgument(
'themeCodes',
InputArgument::IS_ARRAY,
'Theme codes to clean (format: Vendor/theme, Vendor/theme 2, ...)',
'Theme codes to clean (format: Vendor/theme, Vendor, ...)',
)
->addOption('all', 'a', InputOption::VALUE_NONE, 'Clean all themes')
->addOption(
Expand Down Expand Up @@ -105,6 +105,15 @@ private function resolveThemeCodes(InputInterface $input, OutputInterface $outpu
return $this->getAllThemeCodes();
}

if (!empty($themeCodes)) {
$themeCodes = $this->resolveVendorThemes($themeCodes, $this->themeList);

// If wildcards matched nothing and no other explicit themes remain
if (empty($themeCodes)) {
return null;
}
}

if (empty($themeCodes)) {
return $this->selectThemesInteractively($output);
}
Expand Down
Loading