Skip to content

Commit

Permalink
MakeModuleCommand + FilenameSanitizer
Browse files Browse the repository at this point in the history
  • Loading branch information
Chemaclass committed May 30, 2021
1 parent 726beac commit 2ab151d
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 39 deletions.
3 changes: 2 additions & 1 deletion gacela
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Config::setApplicationRootDir($cwd);
$codeGeneratorFactory = new CodeGeneratorFactory();

$application = new Application();
$application->add($codeGeneratorFactory->createMakerCommand());
$application->add($codeGeneratorFactory->createMakerFileCommand());
$application->add($codeGeneratorFactory->createMakerModuleCommand());
$application->run();

18 changes: 17 additions & 1 deletion src/CodeGenerator/CodeGeneratorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,29 @@

use Gacela\CodeGenerator\Domain\CommandArgumentsParser;
use Gacela\CodeGenerator\Domain\FileContentGenerator;
use Gacela\CodeGenerator\Domain\FilenameSanitizer;
use Gacela\CodeGenerator\Infrastructure\Command\MakeFileCommand;
use Gacela\CodeGenerator\Infrastructure\Command\MakeModuleCommand;
use Gacela\Framework\AbstractFactory;

/**
* @method CodeGeneratorConfig getConfig()
*/
final class CodeGeneratorFactory extends AbstractFactory
{
public function createMakerCommand(): MakeFileCommand
public function createMakerModuleCommand(): MakeModuleCommand
{
return new MakeModuleCommand(
$this->createCommandArgumentsParser(),
$this->createFileContentGenerator()
);
}

public function createMakerFileCommand(): MakeFileCommand
{
return new MakeFileCommand(
$this->createCommandArgumentsParser(),
$this->createFilenameSanitizer(),
$this->createFileContentGenerator()
);
}
Expand All @@ -29,6 +40,11 @@ private function createCommandArgumentsParser(): CommandArgumentsParser
);
}

private function createFilenameSanitizer(): FilenameSanitizer
{
return new FilenameSanitizer();
}

private function createFileContentGenerator(): FileContentGenerator
{
return new FileContentGenerator($this->getConfig());
Expand Down
34 changes: 18 additions & 16 deletions src/CodeGenerator/Domain/FileContentGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Gacela\CodeGenerator\Domain\ReadModel\CommandArguments;
use Gacela\CodeGenerator\Infrastructure\Template\CodeTemplateInterface;
use RuntimeException;

final class FileContentGenerator
{
Expand All @@ -16,17 +17,15 @@ public function __construct(CodeTemplateInterface $codeTemplate)
$this->codeTemplate = $codeTemplate;
}

public function generate(
CommandArguments $commandArguments,
string $moduleName
): void {
public function generate(CommandArguments $commandArguments, string $filename): void
{
$this->mkdir($commandArguments->directory());

$path = sprintf('%s/%s.php', $commandArguments->directory(), $moduleName);
$path = sprintf('%s/%s.php', $commandArguments->directory(), $filename);
$search = ['$NAMESPACE$', '$CLASS_NAME$'];
$replace = [$commandArguments->namespace(), $moduleName];
$replace = [$commandArguments->namespace(), $filename];

$template = $this->findTemplate($moduleName);
$template = $this->findTemplate($filename);
$fileContent = str_replace($search, $replace, $template);

file_put_contents($path, $fileContent);
Expand All @@ -38,23 +37,26 @@ private function mkdir(string $directory): void
return;
}
if (!mkdir($directory) && !is_dir($directory)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $directory));
throw new RuntimeException(sprintf('Directory "%s" was not created', $directory));
}
}

private function findTemplate(string $moduleName): string
private function findTemplate(string $filename): string
{
switch (strtolower($moduleName)) {
case 'facade':
switch ($filename) {
case FilenameSanitizer::FACADE:
return $this->codeTemplate->getFacadeMakerTemplate();
case 'factory':
case FilenameSanitizer::FACTORY:
return $this->codeTemplate->getFactoryMakerTemplate();
case 'config':
case FilenameSanitizer::CONFIG:
return $this->codeTemplate->getConfigMakerTemplate();
case 'dependencyprovider':
case FilenameSanitizer::DEPENDENCY_PROVIDER:
return $this->codeTemplate->getDependencyProviderMakerTemplate();

default:
throw new RuntimeException(sprintf(
'Unknown template for "%s"?',
$filename
));
}
throw new \RuntimeException('Unknown template for module ' . $moduleName);
}
}
42 changes: 42 additions & 0 deletions src/CodeGenerator/Domain/FilenameSanitizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace Gacela\CodeGenerator\Domain;

use RuntimeException;

final class FilenameSanitizer
{
public const FACADE = 'Facade';
public const FACTORY = 'Factory';
public const CONFIG = 'Config';
public const DEPENDENCY_PROVIDER = 'DependencyProvider';

private const EXPECTED_FILENAMES = [
self::FACADE,
self::FACTORY,
self::CONFIG,
self::DEPENDENCY_PROVIDER,
];

public function sanitize(string $filename): string
{
$percents = [];
foreach (self::EXPECTED_FILENAMES as $expected) {
$percents[$expected] = similar_text($expected, $filename, $percent);
}

$maxVal = max($percents);
$maxValKeys = array_keys($percents, $maxVal, true);

if (count($maxValKeys) > 1) {
throw new RuntimeException(sprintf(
'Which filename do you mean [%s]?',
implode(' or ', $maxValKeys)
));
}

return reset($maxValKeys);
}
}
28 changes: 8 additions & 20 deletions src/CodeGenerator/Infrastructure/Command/MakeFileCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,26 @@

use Gacela\CodeGenerator\Domain\FileContentGenerator;
use Gacela\CodeGenerator\Domain\CommandArgumentsParser;
use RuntimeException;
use Gacela\CodeGenerator\Domain\FilenameSanitizer;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use function in_array;
use function json_encode;

final class MakeFileCommand extends Command
{
private const EXPECTED_FILENAMES = ['Facade', 'Factory', 'Config', 'DependencyProvider'];

private CommandArgumentsParser $argumentsParser;
private FilenameSanitizer $filenameSanitizer;
private FileContentGenerator $fileContentGenerator;

public function __construct(
CommandArgumentsParser $argumentsParser,
FilenameSanitizer $filenameSanitizer,
FileContentGenerator $fileContentGenerator
) {
parent::__construct('make:file');
$this->argumentsParser = $argumentsParser;
$this->filenameSanitizer = $filenameSanitizer;
$this->fileContentGenerator = $fileContentGenerator;
}

Expand All @@ -43,24 +42,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$path = $input->getArgument('path');
$commandArguments = $this->argumentsParser->parse($path);

/** @var string $filename */
$filename = $input->getArgument('filename');
$filename = ucfirst($filename);
$this->verifyFilename($filename);
$this->fileContentGenerator->generate($commandArguments, $filename);
/** @var string $rawFilename */
$rawFilename = $input->getArgument('filename');
$filename = $this->filenameSanitizer->sanitize($rawFilename);

$this->fileContentGenerator->generate($commandArguments, $filename);
$output->writeln("> Path '$path/$filename' created successfully");

return 0;
}

private function verifyFilename(string $filename): void
{
if (!in_array($filename, self::EXPECTED_FILENAMES)) {
throw new RuntimeException(sprintf(
'Filename must be one of these values: %s',
json_encode(self::EXPECTED_FILENAMES, JSON_THROW_ON_ERROR)
));
}
}
}
66 changes: 66 additions & 0 deletions src/CodeGenerator/Infrastructure/Command/MakeModuleCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

declare(strict_types=1);

namespace Gacela\CodeGenerator\Infrastructure\Command;

use Gacela\CodeGenerator\Domain\CommandArgumentsParser;
use Gacela\CodeGenerator\Domain\FileContentGenerator;
use RuntimeException;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use function in_array;
use function json_encode;

final class MakeModuleCommand extends Command
{
private const FILENAMES = ['Facade', 'Factory', 'Config', 'DependencyProvider'];

private CommandArgumentsParser $argumentsParser;
private FileContentGenerator $fileContentGenerator;

public function __construct(
CommandArgumentsParser $argumentsParser,
FileContentGenerator $fileContentGenerator
) {
parent::__construct('make:module');
$this->argumentsParser = $argumentsParser;
$this->fileContentGenerator = $fileContentGenerator;
}

protected function configure(): void
{
$this->setDescription('Generate a basic module with an empty Facade|Factory|Config|DependencyProvider.')
->addArgument('path', InputArgument::REQUIRED, 'The file path. For example "App/TestModule/TestSubModule"');
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
/** @var string $path */
$path = $input->getArgument('path');
$commandArguments = $this->argumentsParser->parse($path);

foreach (self::FILENAMES as $filename) {
$this->fileContentGenerator->generate($commandArguments, $filename);
$output->writeln("> Path '$path/$filename' created successfully");
}

$pieces = explode('/', $commandArguments->directory());
$moduleName = end($pieces);
$output->writeln("Module '$moduleName' created successfully");

return 0;
}

private function verifyFilename(string $filename): void
{
if (!in_array($filename, self::FILENAMES)) {
throw new RuntimeException(sprintf(
'Filename must be one of these values: %s',
json_encode(self::FILENAMES, JSON_THROW_ON_ERROR)
));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace GacelaTest\Unit\CodeGenerator;
namespace GacelaTest\Unit\CodeGenerator\Domain;

use Gacela\CodeGenerator\Domain\CommandArgumentsParser;
use Gacela\CodeGenerator\Domain\Exception\CommandArgumentsException;
Expand Down
Loading

0 comments on commit 2ab151d

Please sign in to comment.