Skip to content

Commit

Permalink
ControlJob
Browse files Browse the repository at this point in the history
  • Loading branch information
martenb committed Apr 13, 2020
1 parent 22a6e94 commit c0102b0
Show file tree
Hide file tree
Showing 7 changed files with 264 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ extensions:
# Generate command for symfony/command package
php bin/console worker:command [options] [--] [<name>]

# Generate control with factory and template
php bin/console worker:control [options] [--] [<name>]

# Generate model for nextras/orm package
php bin/console worker:orm [options] [--] [<entity> [<repository>]]

Expand Down
1 change: 1 addition & 0 deletions src/DI/WorkerExtension.neon
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
services:
- Adbros\Worker\Jobs\CommandJob
- Adbros\Worker\Jobs\ControlJob
- Adbros\Worker\Jobs\OrmJob
- Adbros\Worker\Jobs\PresenterJob
155 changes: 155 additions & 0 deletions src/Jobs/ControlJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php declare(strict_types = 1);

namespace Adbros\Worker\Jobs;

use Nette\PhpGenerator\PhpFile;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\InvalidOptionException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Style\SymfonyStyle;

class ControlJob extends AbstractJob
{

public static function getCommandName(): string
{
return 'worker:control';
}

public function configureCommand(Command $command): void
{
parent::configureCommand($command);

$command
->setDescription('Generate control with factory and template.')
->addArgument('name', InputArgument::OPTIONAL, 'Control name')
->addOption('namespace', 'ns', InputOption::VALUE_OPTIONAL, 'Control namespace')
->addOption('control-parent', 'cp', InputOption::VALUE_OPTIONAL, 'Control parent class')
->addOption('factory-parent', 'fp', InputOption::VALUE_OPTIONAL, 'Factory parent class');
}

public function interact(InputInterface $input, SymfonyStyle $io, Command $command): void
{
parent::interact($input, $io, $command);

if (!$this->isClass($input->getArgument('name'))) {
$name = $io->ask('Enter control name', null, function (?string $answer): string {
if (!$this->isClass($answer)) {
throw new InvalidArgumentException('Please, enter valid control name.');
}

return $answer;
});

$input->setArgument('name', $name);
}

if (!$this->isNamespace($input->getOption('namespace'), $input->getOption('root-namespace'))) {
$namespace = $io->ask('Enter control namespace', $input->getOption('root-namespace') . '\\Controls\\' . $input->getArgument('name'), function (?string $answer) use ($input): string {
if (!$this->isNamespace($answer, $input->getOption('root-namespace'))) {
throw new InvalidOptionException('Please, enter valid control namespace.');
}

return $answer;
});

$input->setOption('namespace', $namespace);
}

if (!$this->isNamespace($input->getOption('control-parent'))) {
$namespace = $io->ask('Enter entity parent class', 'Nette\\Application\\UI\\Control', function (?string $answer): string {
if (!$this->isNamespace($answer)) {
throw new InvalidOptionException('Please, enter valid control parent class.');
}

return $answer;
});

$input->setOption('control-parent', $namespace);
}

if ($input->getOption('factory-parent') !== '' && !$this->isNamespace($input->getOption('factory-parent'))) {
$namespace = $io->ask('Enter factory parent class', '', function (?string $answer): string {
if ($answer !== '' && !$this->isNamespace($answer)) {
throw new InvalidOptionException('Please, enter valid factory parent class.');
}

return $answer;
});

$input->setOption('factory-parent', $namespace);
}
}

public function generate(InputInterface $input, SymfonyStyle $io): int
{
$directory = $input->getOption('root-directory') .
$this->namespaceToPath($input->getOption('namespace'), $input->getOption('root-namespace'));

if (file_exists($directory)) {
throw new RuntimeException(sprintf('Directory %s already exists!', $directory));
}

mkdir($directory, 0777, true);

$file = new PhpFile();

if (method_exists($file, 'setStrictTypes')) {
$file->setStrictTypes(true);
}

$file
->addNamespace($input->getOption('namespace'))
->addUse($input->getOption('control-parent'))
->addClass($input->getArgument('name') . 'Control')
->setExtends($input->getOption('control-parent'))
->addMethod('render')
->setReturnType('void')
->setBody('$this->template->setFile(\'' . $input->getArgument('name') . 'Control.latte\');' . "\n" . '$this->template->render();');

file_put_contents(($filename = $directory . '/' . $input->getArgument('name') . 'Control.php'), (string) $file);

$io->text(sprintf('File %s created.', $filename));

$file = new PhpFile();

if (method_exists($file, 'setStrictTypes')) {
$file->setStrictTypes(true);
}

$namespace = $file
->addNamespace($input->getOption('namespace'));

if ($input->getOption('factory-parent') !== '') {
$namespace
->addUse($input->getOption('factory-parent'));
}

$class = $namespace
->addClass($input->getArgument('name') . 'Control');

if ($input->getOption('factory-parent') !== '') {
$class
->setExtends($input->getOption('factory-parent'));
}

$class->addMethod('create')
->setReturnType($input->getOption('namespace') . '\\' . $input->getArgument('name') . 'Control')
->setBody('return new ' . $input->getArgument('name') . 'Control();');

file_put_contents(($filename = $directory . '/' . $input->getArgument('name') . 'Factory.php'), (string) $file);

$io->text(sprintf('File %s created.', $filename));

file_put_contents(($filename = $directory . '/' . $input->getArgument('name') . 'Control.latte'), '');

$io->text(sprintf('File %s created.', $filename));

return 0;
}

}
74 changes: 74 additions & 0 deletions tests/cases/Jobs/ControlJobTest.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php declare(strict_types = 1);

namespace Adbros\Worker\Tests\Jobs;

use Adbros\Worker\Command\WorkerCommand;
use Adbros\Worker\FileManager;
use Adbros\Worker\Jobs\ControlJob;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Tester\Assert;

require_once __DIR__ . '/../../bootstrap.php';

/**
* @testCase
*/
class ControlJobTest extends JobsTestCase
{

public function setUp(): void
{
$this->inputs = [
'--root-directory' => OUTPUT_DIR,
'--root-namespace' => 'My\\App',
'name' => 'Test',
'--namespace' => 'My\\App\\My\\Controls\\Test',
'--control-parent' => 'My\\App\\My\\Controls\\BaseControl',
'--factory-parent' => 'My\\App\\My\\Controls\\BaseFactory',
];
}

public function testNoninteractive(): void
{
$fileManager = new FileManager('');

$command = new WorkerCommand(new ControlJob($fileManager));

$input = new ArrayInput($this->inputs);

$output = new BufferedOutput();

Assert::same(0, $command->run($input, $output));

Assert::same(file_get_contents(__DIR__ . '/expected/ControlJob.control.expect'), file_get_contents(OUTPUT_DIR . '/My/Controls/Test/TestControl.php'));

Assert::same(file_get_contents(__DIR__ . '/expected/ControlJob.factory.expect'), file_get_contents(OUTPUT_DIR . '/My/Controls/Test/TestFactory.php'));

Assert::same(file_get_contents(__DIR__ . '/expected/ControlJob.template.expect'), file_get_contents(OUTPUT_DIR . '/My/Controls/Test/TestControl.latte'));
}

public function testInteractive(): void
{
$fileManager = new FileManager('');

$command = new WorkerCommand(new ControlJob($fileManager));

$input = new ArrayInput([]);

$input->setStream($this->createStream($this->inputs));

$output = new BufferedOutput();

Assert::same(0, $command->run($input, $output));

Assert::same(file_get_contents(__DIR__ . '/expected/ControlJob.control.expect'), file_get_contents(OUTPUT_DIR . '/My/Controls/Test/TestControl.php'));

Assert::same(file_get_contents(__DIR__ . '/expected/ControlJob.factory.expect'), file_get_contents(OUTPUT_DIR . '/My/Controls/Test/TestFactory.php'));

Assert::same(file_get_contents(__DIR__ . '/expected/ControlJob.template.expect'), file_get_contents(OUTPUT_DIR . '/My/Controls/Test/TestControl.latte'));
}

}

(new ControlJobTest())->run();
16 changes: 16 additions & 0 deletions tests/cases/Jobs/expected/ControlJob.control.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace My\App\My\Controls\Test;

use My\App\My\Controls\BaseControl;

class TestControl extends BaseControl
{
public function render(): void
{
$this->template->setFile('TestControl.latte');
$this->template->render();
}
}
15 changes: 15 additions & 0 deletions tests/cases/Jobs/expected/ControlJob.factory.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace My\App\My\Controls\Test;

use My\App\My\Controls\BaseFactory;

class TestControl extends BaseFactory
{
public function create(): TestControl
{
return new TestControl();
}
}
Empty file.

0 comments on commit c0102b0

Please sign in to comment.