Completed
Push — master ( f1c264...f58245 )
by Thomas
04:22
created

GenerateDomainCommand   C

Complexity

Total Complexity 18

Size/Duplication

Total Lines 147
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 21

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 18
c 3
b 0
f 0
lcom 1
cbo 21
dl 0
loc 147
rs 6.1111

7 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 21 1
A initialize() 0 6 1
A preCheck() 0 6 2
B interact() 0 36 6
B execute() 0 29 4
A generateModel() 0 16 2
A generateSkeleton() 0 15 2
1
<?php
2
namespace keeko\tools\command;
3
4
use keeko\tools\generator\domain\base\ModelDomainTraitGenerator;
5
use keeko\tools\generator\domain\base\ReadOnlyModelDomainTraitGenerator;
6
use keeko\tools\generator\domain\ModelDomainGenerator;
7
use keeko\tools\generator\domain\SkeletonDomainGenerator;
8
use keeko\tools\helpers\QuestionHelperTrait;
9
use keeko\tools\utils\NamespaceResolver;
10
use phootwork\lang\Text;
11
use Symfony\Component\Console\Input\InputArgument;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Input\InputOption;
14
use Symfony\Component\Console\Output\OutputInterface;
15
use Symfony\Component\Console\Question\ConfirmationQuestion;
16
use Symfony\Component\Console\Question\Question;
17
18
class GenerateDomainCommand extends AbstractGenerateCommand {
19
20
	use QuestionHelperTrait;
21
	
22
	private $twig;
23
24
	protected function configure() {
25
		$this
26
			->setName('generate:domain')
27
			->setDescription('Generates a domain object')
28
			->addArgument(
29
				'name',
30
				InputArgument::OPTIONAL,
31
				'The name of the action, which should be generated. Typically in the form %nomen%-%verb% (e.g. user-create)'
32
			)
33
			->addOption(
34
				'model',
35
				'm',
36
				InputOption::VALUE_OPTIONAL,
37
				'The model for which the actions should be generated, when there is no name argument (if ommited all models will be generated)'
38
			)
39
		;
40
		
41
		$this->configureGenerateOptions();
42
		
43
		parent::configure();
44
	}
45
46
	protected function initialize(InputInterface $input, OutputInterface $output) {
47
		parent::initialize($input, $output);
48
49
		$loader = new \Twig_Loader_Filesystem($this->service->getConfig()->getTemplateRoot() . '/domain');
50
		$this->twig = new \Twig_Environment($loader);
51
	}
52
53
	/**
54
	 * Checks whether actions can be generated at all by reading composer.json and verify
55
	 * all required information are available
56
	 */
57
	private function preCheck() {
58
		$module = $this->packageService->getModule();
59
		if ($module === null) {
60
			throw new \DomainException('No module definition found in composer.json - please run `keeko init`.');
61
		}
62
	}
63
	
64
	protected function interact(InputInterface $input, OutputInterface $output) {
65
		$this->preCheck();
66
		
67
		// check if the dialog can be skipped
68
		$name = $input->getArgument('name');
69
		$model = $input->getOption('model');
70
		
71
		if ($model !== null) {
72
			return;
73
		} else if ($name !== null) {
74
			$generateModel = false;
75
		} else {
76
			$modelQuestion = new ConfirmationQuestion('Do you want to generate a domain object based off a model?');
77
			$generateModel = $this->askConfirmation($modelQuestion);
78
		}
79
		
80
		// ask questions for a model
81
		if ($generateModel !== false) {
82
			$schema = str_replace(getcwd(), '', $this->modelService->getSchema());
83
			$allQuestion = new ConfirmationQuestion(sprintf('For all models in the schema (%s)?', $schema));
84
			$allModels = $this->askConfirmation($allQuestion);
85
86
			if (!$allModels) {
87
				$modelQuestion = new Question('Which model');
88
				$modelQuestion->setAutocompleterValues($this->modelService->getModelNames());
89
				$model = $this->askQuestion($modelQuestion);
90
				$input->setOption('model', $model);
91
			}
92
			
93
		// ask question for a skeleton
94
		} else if (empty($name)) {
95
			// ask for classname
96
			$name = $this->askQuestion(new Question('Classname', $name));
97
			$input->setArgument('name', $name);
98
		}
99
	}
100
101
	protected function execute(InputInterface $input, OutputInterface $output) {
102
		$this->preCheck();
103
		
104
		// 1. find out which action(s) to generate
105
		// 2. generate the information in the package
106
		// 3. generate the code for the action
107
		
108
		$name = $input->getArgument('name');
109
		$model = $input->getOption('model');
110
111
		// generate a skeleton
112
		if ($name) {
113
			$this->generateSkeleton($name);
114
		}
115
116
		// create domain for one model
117
		else if ($model) {
118
			$this->generateModel($model);
119
		}
120
121
		// generate domain for all models
122
		else {
123
			foreach ($this->modelService->getModels() as $model) {
124
				$modelName = $model->getOriginCommonName();
125
				$input->setOption('model', $modelName);
126
				$this->generateModel($modelName);
127
			}
128
		}
129
	}
130
131
	private function generateModel($modelName) {
132
		$this->logger->info('Generate Domain from Model: ' . $modelName);
133
		$model = $this->modelService->getModel($modelName);
134
		
135
		// generate class
136
		$generator = new ModelDomainGenerator($this->service);
137
		$class = $generator->generate($model);
138
		$this->codegenService->dumpStruct($class, true);
139
		
140
		// generate trait
141
		$generator = $model->isReadOnly()
142
			? new ReadOnlyModelDomainTraitGenerator($this->service)
143
			: new ModelDomainTraitGenerator($this->service);
144
		$trait = $generator->generate($model);
145
		$this->codegenService->dumpStruct($trait, true);
146
	}
147
	
148
	private function generateSkeleton($name) {
149
		$this->logger->info('Generate Skeleton Domain: ' . $name);
150
		$input = $this->io->getInput();
151
152
		$className = NamespaceResolver::getNamespace('src/domain', $this->package) . '\\' . $name;
153
		
154
		if (!Text::create($className)->endsWith('Domain')) {
155
			$className .= 'Domain';
156
		}
157
158
		// generate code
159
		$generator = new SkeletonDomainGenerator($this->service);
160
		$class = $generator->generate($className);
161
		$this->codegenService->dumpStruct($class, $input->getOption('force'));
162
	}
163
	
164
}
165