Completed
Push — master ( c9073d...17137d )
by Thomas
17:02
created

GenerateResponseCommand::configure()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 31
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 1

Importance

Changes 7
Bugs 0 Features 0
Metric Value
c 7
b 0
f 0
dl 0
loc 31
ccs 21
cts 21
cp 1
rs 8.8571
cc 1
eloc 23
nc 1
nop 0
crap 1
1
<?php
2
namespace keeko\tools\command;
3
4
use gossi\codegen\model\PhpClass;
5
use keeko\tools\generator\GeneratorFactory;
6
use keeko\tools\generator\response\base\ModelResponseTraitGenerator;
7
use keeko\tools\generator\response\BlankHtmlResponseGenerator;
8
use keeko\tools\generator\response\BlankJsonResponseGenerator;
9
use keeko\tools\generator\response\TwigHtmlResponseGenerator;
10
use keeko\tools\helpers\QuestionHelperTrait;
11
use phootwork\collection\Set;
12
use Symfony\Component\Console\Input\InputArgument;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Input\InputOption;
15
use Symfony\Component\Console\Output\OutputInterface;
16
use Symfony\Component\Console\Question\ConfirmationQuestion;
17
use Symfony\Component\Console\Question\Question;
18
use phootwork\file\File;
19
use keeko\tools\generator\response\DumpJsonResponseGenerator;
20
21
class GenerateResponseCommand extends AbstractGenerateCommand {
22
23
	use QuestionHelperTrait;
24 20
	
25 20
	protected $traits;
26 20
	
27 20
	protected function configure() {
28 20
		$this->traits = new Set();
29 20
		
30 20
		$this
31
			->setName('generate:response')
32 20
			->setDescription('Generates code for a response')
33 20
			->addArgument(
34 20
				'name',
35 20
				InputArgument::OPTIONAL,
36 20
				'The name of the action, which should be generated. Typically in the form %nomen%-%verb% (e.g. user-create)'
37 20
			)
38
			->addOption(
39 20
				'format',
40 20
				'',
41 20
				InputOption::VALUE_OPTIONAL,
42 20
				'The response format to create',
43 20
				'json'
44 20
			)
45 1
			->addOption(
46 20
				'template',
47
				'',
48
				InputOption::VALUE_OPTIONAL,
49 20
				'The template for the body method (blank or twig)',
50
				'blank'
51 20
			)
52 20
		;
53
		
54
		$this->configureGenerateOptions();
55
56
		parent::configure();
57
	}
58 7
59 7
	/**
60 7
	 * Checks whether actions can be generated at all by reading composer.json and verify
61 1
	 * all required information are available
62
	 */
63 6
	private function preCheck() {
64
		$module = $this->packageService->getModule();
65
		if ($module === null || count($module->getActionNames()) == 0) {
66
			throw new \DomainException('No action definition found in composer.json - please run `keeko generate:action`.');
67
		}
68
	}
69
70
	protected function interact(InputInterface $input, OutputInterface $output) {
71
		$this->preCheck();
72
		
73
		// check if the dialog can be skipped
74
		$name = $input->getArgument('name');
75
		$specificAction = false;
76
		
77
		if ($name === null) {
78
			$specificQuestion = new ConfirmationQuestion('Do you want to generate a response for a specific action?');
79
			$specificAction = $this->askConfirmation($specificQuestion);
80
		}
81
		
82
		// ask which action
83
		if ($specificAction) {
84
			$names = [];
85
			$module = $this->packageService->getModule();
86
			foreach ($module->getActionNames() as $name) {
87
				$names[] = $name;
88
			}
89
			
90
			$actionQuestion = new Question('Which action');
91
			$actionQuestion->setAutocompleterValues($names);
92
			$name = $this->askQuestion($actionQuestion);
93
			$input->setArgument('name', $name);
94
		} 
95
		
96
		
97
		// ask which format
98
		$formatQuestion = new Question('Which format', 'json');
99
		$formatQuestion->setAutocompleterValues(['json', 'html']);
100
		$format = $this->askQuestion($formatQuestion);
101
		$input->setOption('format', $format);
102
		
103
		// ask which template
104
		$templates = [
105 7
			'html' => ['twig', 'blank'],
106 7
			'json' => ['dump', 'blank']
107
		];
108 6
		
109
		$suggestions = isset($templates[$format]) ? $templates[$format] : [];
110
		$default = count($suggestions) ? $suggestions[0] : '';
111 6
		$templateQuestion = new Question('Which template', $default);
112 5
		$templateQuestion->setAutocompleterValues($suggestions);
113 4
		$template = $this->askQuestion($templateQuestion);
114
		$input->setOption('template', $template);
115
		
116
	}
117 1
118
	protected function execute(InputInterface $input, OutputInterface $output) {
119 1
		$this->preCheck();
120 1
		
121 1
		$name = $input->getArgument('name');
122
123
		// only a specific action
124 5
		if ($name) {
125 5
			$this->generateResponse($name);
126
		}
127 6
		
128 6
		// anyway all actions
129
		else {
130 6
			$actions = $this->packageService->getModule()->getActionNames();
131 1
			
132
			foreach ($actions as $name) {
133
				$this->generateResponse($name);
134 5
			}
135 5
		}
136 5
		
137 5
		$this->packageService->savePackage();
138 5
	}
139
	
140 5
	private function generateResponse($actionName) {
141 5
		$this->logger->info('Generate Response: ' . $actionName);
142 5
		$module = $this->packageService->getModule();
143
		
144
		if (!$module->hasAction($actionName)) {
145 5
			throw new \RuntimeException(sprintf('action (%s) not found', $actionName));
146 5
		}
147 5
		
148
		$input = $this->io->getInput();
149
		$action = $module->getAction($actionName);
150 5
		$modelName = $this->modelService->getModelNameByAction($action);
151 2
		$format = $input->getOption('format');
152 2
		$template = $input->getOption('template');
153
154
		if (!$action->hasResponse($format)) {
155 4
			$action->setResponse($format, str_replace(['Action', 'action'], [ucwords($format) . 'Response', 'response'], $action->getClass()));
156 2
		}
157 2
158
		// find generator
159
		$overwrite = false;
160 2
		$generator = null;
161 1
		$type = $this->packageService->getActionType($actionName, $modelName);
162 1
		$isModel = $type && $this->modelService->isModelAction($action); 
163
164
		// model given and format is json
165 1
		if ($isModel && $format === 'json') {
166 1
			$generator = GeneratorFactory::createJsonResponseGenerator($type, $this->service);
167 1
		}
168
		
169
		// json + dump
170 5
		else if ($format === 'json' && $template == 'dump') {
171
			$generator = new DumpJsonResponseGenerator($this->service);
172 5
		}
173
		
174
		// blank json
175 5
		else if ($format === 'json') {
176 2
			$generator = new BlankJsonResponseGenerator($this->service);
177 2
		}
178 2
		
179
		// html + twig
180 2
		else if ($format === 'html' && $template == 'twig') {
181 2
			$generator = new TwigHtmlResponseGenerator($this->service);
182 2
		}
183 2
		
184 2
		// blank html as default
185
		else if ($format == 'html') {
186
			$generator = new BlankHtmlResponseGenerator($this->service);
187 5
		}
188 5
		
189 5
		// run generation, if generator was chosen
190
		if ($generator !== null) {
191
			/* @var $class PhpClass */
192
			$class = $generator->generate($action);
193
			
194
			// generate json trait
195
			if ($isModel && $format === 'json') {
196
				$generator = new ModelResponseTraitGenerator($this->service);
197
				$trait = $generator->generate($action);
198
				
199
				if (!$class->hasTrait($trait)) {
200
					$class->addTrait($trait);
0 ignored issues
show
Documentation introduced by
$trait is of type object<gossi\codegen\model\PhpClass>, but the function expects a object<gossi\codegen\model\PhpTrait>|string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
201
					$overwrite = true;
202
				}
203
				
204
				if (!$this->traits->contains($trait->getName())) {
205
					$this->codegenService->dumpStruct($trait, true);
206
					$this->traits->add($trait->getName());
207
				}
208
			}
209
210
			// write to file
211
			$file = new File($this->codegenService->getFilename($class));
212
			if (!$file->exists()) {
213
				$overwrite = true;
214
			}
215
			$overwrite = $overwrite || $input->getOption('force');
216
			$this->codegenService->dumpStruct($class, $overwrite);
217
		}
218
	}
219
220
}
221