Skip to content
Closed
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>...]
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the usage line, the placeholder name <themename> is inconsistent with the actual CLI argument name (themeCodes) used in the command definition and with the build command’s docs. Consider changing it to something like <themeCodes>... for consistency.

Suggested change
bin/magento mageforge:theme:clean [<themename>...]
bin/magento mageforge:theme:clean [<themeCodes>...]

Copilot uses AI. Check for mistakes.
```

**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
2 changes: 1 addition & 1 deletion release-please-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"include-v-in-tag": false,
"include-component-in-tag": false,
"pull-request-title-pattern": "chore: Next Release ${version}",
"pull-request-header": "## Release ${version}",
"pull-request-header": "## Upcoming Release",
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description says this only updates the release-please PR header, but this PR also changes multiple CLI commands and documentation. Please update the PR title/description to reflect the full scope (vendor/wildcard theme code resolution + build summary output) so reviewers understand the risk/intent.

Copilot uses AI. Check for mistakes.
"changelog-sections": [
{
"type": "feat",
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>
*/
Comment on lines +483 to +489
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new helper’s PHPDoc says it resolves vendor theme codes, but the implementation also supports explicit wildcard inputs like Vendor/*. Please update the docblock summary to match the actual supported inputs/behavior.

Copilot uses AI. Check for mistakes.
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, ...)',
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The argument help text documents vendor-only inputs (e.g. Vendor) but the command also supports explicit wildcards like Vendor/* via resolveVendorThemes(). Consider updating the help text to mention Vendor/* (or remove wildcard support/comment if it’s not intended) so CLI usage is not misleading.

Suggested change
'Theme codes to build (format: Vendor/theme, Vendor, ...)',
'Theme codes to build (format: Vendor/theme, Vendor, Vendor/*, ...)',

Copilot uses AI. Check for mistakes.
)
->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
Comment on lines +70 to +74
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inline comment says this block is for “wildcards”, but resolveVendorThemes() also expands vendor-only inputs (e.g. Vendor). Please adjust the comment to reflect both behaviors to avoid misleading future readers.

Suggested change
// 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
// Resolve vendor-only inputs and wildcard patterns using the helper
if (!empty($themeCodes)) {
$themeCodes = $this->resolveVendorThemes($themeCodes, $this->themeList);
// If resolution matched no themes and no other explicit themes remain

Copilot uses AI. Check for mistakes.
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, ...)',
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The argument help text documents vendor-only inputs (e.g. Vendor) but the command also supports explicit wildcards like Vendor/* via resolveVendorThemes(). Consider updating the help text to mention Vendor/* (or remove wildcard support/comment if it’s not intended) so CLI usage is not misleading.

Suggested change
'Theme codes to clean (format: Vendor/theme, Vendor, ...)',
'Theme codes to clean (format: Vendor/theme, Vendor, Vendor/*, ...)',

Copilot uses AI. Check for mistakes.
)
->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