An error occurred while loading the file. Please try again.
-
Petr Besir Horáček authored
<?php
declare(strict_types=1);
namespace MondayFactory\DatabaseModelGenerator\Command;
use MondayFactory\DatabaseModelGenerator\Generator\CollectionGenerator;
use MondayFactory\DatabaseModelGenerator\Generator\DataGenerator;
use MondayFactory\DatabaseModelGenerator\Generator\LowLevelDatabaseStorageGenerator;
use Nette\IOException;
use Nette\Neon\Neon;
use Nette\Utils\FileSystem;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class GenerateBasicModel extends Command
{
public const COMMAND_NAME = 'basic-model';
/**
* @var array
*/
private $definition;
/**
* @var string
*/
private $neonName;
/**
* @var array
*/
private $generators = ['collection', 'data', 'llstorage'];
/**
* @var bool
*/
private $printToStdOut;
/**
* @var bool
*/
private $dryRun;
/**
* @var bool
*/
private $force;
/**
* @var OutputInterface
*/
private $output;
/**
* @var string
*/
private $projectFilesPath;
/**
* @var InputInterface
*/
private $input;
public function __construct()
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
{
parent::__construct();
}
protected function configure(): void
{
$this->setName(self::COMMAND_NAME);
$this->setDescription('Generates basic MondayFactory Model files from definition.');
$this->addArgument('neonName', InputArgument::REQUIRED, 'Name of the neon with definition.');
$this->addArgument(
'projectFilesPath',
InputArgument::REQUIRED,
'Path to the project files e.g. "app", or absolute "/data/app". Default is used getcwd(): ' . getcwd() . '.');
$this->addArgument(
'whatGenerate',
InputArgument::IS_ARRAY | InputArgument::OPTIONAL ,
'What You need to generate? You can add more types as list separated by space.
For all leave argument blank. Allowed values:
[' . join(', ', $this->generators) . ']' , ['collection', 'data', 'llstorage']);
$this->addOption('def-dir', null, InputOption::VALUE_REQUIRED, '', null);
$this->addOption('ignored-namespace', 'I', InputOption::VALUE_REQUIRED, '', null);
$this->addOption('p', 'p', InputOption::VALUE_NONE);
$this->addOption('dry-run', null, InputOption::VALUE_NONE);
$this->addOption('force', 'f', InputOption::VALUE_NONE);
}
/**
* @throws \InvalidArgumentException
*/
protected function execute(InputInterface $input, OutputInterface $output): void
{
$this->input = $input;
if (is_string($input->getArgument('projectFilesPath'))) {
$this->projectFilesPath = $input->getArgument('projectFilesPath');
} else {
throw new \InvalidArgumentException('Parameter projectFilesPath must be string.');
}
$this->printToStdOut = is_bool($input->getOption('p'))
? $input->getOption('p')
: false;
$this->dryRun = is_bool($input->getOption('dry-run'))
? $input->getOption('dry-run')
: false;
$this->force = is_bool($input->getOption('force'))
? $input->getOption('force')
: false;
$this->output = $output;
if ($this->dryRun) {
$this->output->write("<fg=yellow>Dry run!</>", true);
}
try {
if (! is_string($input->getArgument('neonName'))) {
throw new \InvalidArgumentException('Neon name must be string.');
}
$this->neonName = $input->getArgument('neonName');
$neon = $this->resolveNenonPath();
$neonContent = file_get_contents($neon);
if ($neonContent === false) {
throw new \UnexpectedValueException('Neon file can not be read.');
}
$this->definition = Neon::decode($neonContent);
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
} catch (\Exception $e) {
$output->writeln($e->getMessage());
return;
}
$whatGenerate = is_array($input->getArgument('whatGenerate'))
? $input->getArgument('whatGenerate')
: $this->generators;
foreach ($whatGenerate as $generator) {
if (! in_array($generator, $this->generators, true)) {
$output->writeln("Generator {$generator} is not allowed. Skipping.");
continue;
}
switch ($generator) {
case 'collection':
$this->generateCollection();
break;
case 'data':
$this->generateData();
break;
case 'llstorage':
$this->generateLlstorage();
break;
}
}
$this->output->writeln("<fg=green>Done.</>");
}
private function generateCollection(): void
{
$collectionGenerator = new CollectionGenerator($this->definition, $this->getNeonName());
$this->processOutput($collectionGenerator->getContent(), $collectionGenerator->getFileNamespace());
}
private function generateData(): void
{
$dataGenerator = new DataGenerator($this->definition, $this->getNeonName());
$this->processOutput($dataGenerator->getContent(), $dataGenerator->getFileNamespace());
}
private function generateLlstorage(): void
{
$lowLevelDatabaseStorage = new LowLevelDatabaseStorageGenerator($this->definition, $this->getNeonName());
$this->processOutput($lowLevelDatabaseStorage->getContent(), $lowLevelDatabaseStorage->getFileNamespace());
}
private function processOutput(string $output, string $filePath): void
{
$this->write($output, $filePath);
}
private function write(string $content, string $namespace): void
{
$namespace = ltrim(str_replace('\\', '/', $namespace), '/');
if (is_string($this->input->getOption('ignored-namespace')))
{
$ignoredFileSpace = str_replace('\\', '/', $this->input->getOption('ignored-namespace'));
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
$ignoredFileSpace = rtrim(ltrim($ignoredFileSpace, '/'), '/');
$namespace = ltrim(substr($namespace, strlen($ignoredFileSpace)), '/');
}
$projectFilesPath = '';
if (strlen($this->projectFilesPath) > 0) {
$projectFilesPath = substr($this->projectFilesPath, 0, 1) === '/'
? realpath($this->projectFilesPath)
: realpath(getcwd() . '/' . $this->projectFilesPath);
} else {
$cwd = getcwd();
$projectFilesPath = $cwd !== false
? realpath($cwd)
: false;
}
$projectFilesPath = $projectFilesPath === false
? ''
: $projectFilesPath;
$fileName = $projectFilesPath . '/' . $namespace . '.php';
if ($this->dryRun) {
if (file_exists($fileName)) {
$this->output->write("<fg=red>File {$fileName} exists. You must use force (--force|-f) to recreate.</>", true);
} else {
$this->output->write("<fg=green>File {$fileName} is ready for create.</>", true);
}
}
if ($this->printToStdOut) {
if (! $this->dryRun) {
$this->output->write("<fg=green>{$fileName}</>", true);
}
try {
$oldFileContent = file_get_contents($fileName);
require_once 'SideBySide.php';
$diff = new \SideBySide();
$diff->setAffixes(\SideBySide::AFFIXES_CLI);
echo $diff->compute($oldFileContent, $content)[1];
} catch (\Exception $e) {
$this->output->writeln($content);
}
}
if (! $this->dryRun) {
if ($this->force) {
try {
FileSystem::write($fileName, $content);
} catch (IOException $e) {
$this->output->write("<fg=red>File {$fileName} cannot be written.</> " . $e->getMessage(), true);
}
} else {
if (! file_exists($fileName)) {
try {
FileSystem::write($fileName, $content);
} catch (IOException $e) {
$this->output->write("<fg=red>File {$fileName} cannot be written.</> " . $e->getMessage(), true);
}
} else {
$this->output->write("<fg=red>File {$fileName} exists. Use force (--force|-f) if you need recreate the model.</>", true);
}
}
}
}