Completed
Push — master ( 886536...023239 )
by Thomas
07:27
created

GenerateDomainCommand::preCheck()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 2
eloc 4
nc 2
nop 0
1
<?php
2
namespace keeko\tools\command;
3
4
use keeko\framework\schema\ActionSchema;
5
use keeko\framework\utils\NameUtils;
6
use keeko\tools\generator\domain\DomainGenerator;
7
use keeko\tools\generator\domain\DomainTraitGenerator;
8
use keeko\tools\generator\domain\ReadOnlyDomainTraitGenerator;
9
use keeko\tools\helpers\QuestionHelperTrait;
10
use keeko\tools\utils\NamespaceResolver;
11
use phootwork\lang\Text;
12
use Propel\Generator\Model\Table;
13
use Symfony\Component\Console\Input\InputArgument;
14
use Symfony\Component\Console\Input\InputInterface;
15
use Symfony\Component\Console\Input\InputOption;
16
use Symfony\Component\Console\Output\OutputInterface;
17
use Symfony\Component\Console\Question\ConfirmationQuestion;
18
use Symfony\Component\Console\Question\Question;
19
20
class GenerateDomainCommand extends AbstractGenerateCommand {
21
22
	use QuestionHelperTrait;
23
	
24
	private $twig;
25
26
	protected function configure() {
27
		$this
28
			->setName('generate:domain')
29
			->setDescription('Generates a domain object')
30
			->addArgument(
31
				'name',
32
				InputArgument::OPTIONAL,
33
				'The name of the action, which should be generated. Typically in the form %nomen%-%verb% (e.g. user-create)'
34
			)
35
			->addOption(
36
				'classname',
37
				'c',
38
				InputOption::VALUE_OPTIONAL,
39
				'The main class name (If ommited, class name will be guessed from action name)',
40
				null
41
			)
42
			->addOption(
43
				'model',
44
				'm',
45
				InputOption::VALUE_OPTIONAL,
46
				'The model for which the actions should be generated, when there is no name argument (if ommited all models will be generated)'
47
			)
48
		;
49
		
50
		$this->configureGenerateOptions();
51
		
52
		parent::configure();
53
	}
54
55
	protected function initialize(InputInterface $input, OutputInterface $output) {
56
		parent::initialize($input, $output);
57
58
		$loader = new \Twig_Loader_Filesystem($this->service->getConfig()->getTemplateRoot() . '/domain');
59
		$this->twig = new \Twig_Environment($loader);
60
	}
61
62
	/**
63
	 * Checks whether actions can be generated at all by reading composer.json and verify
64
	 * all required information are available
65
	 */
66
	private function preCheck() {
67
		$module = $this->packageService->getModule();
68
		if ($module === null) {
69
			throw new \DomainException('No module definition found in composer.json - please run `keeko init`.');
70
		}
71
	}
72
	
73
	protected function interact(InputInterface $input, OutputInterface $output) {
74
		$this->preCheck();
75
		
76
		// check if the dialog can be skipped
77
		$name = $input->getArgument('name');
78
		$model = $input->getOption('model');
79
		
80
		if ($model !== null) {
81
			return;
82
		} else if ($name !== null) {
83
			$generateModel = false;
84
		} else {
85
			$modelQuestion = new ConfirmationQuestion('Do you want to generate a domain object based off a model?');
86
			$generateModel = $this->askConfirmation($modelQuestion);
87
		}
88
		
89
		// ask questions for a model
90
		if ($generateModel) {
91
			$schema = str_replace(getcwd(), '', $this->modelService->getSchema());
92
			$allQuestion = new ConfirmationQuestion(sprintf('For all models in the schema (%s)?', $schema));
93
			$allModels = $this->askConfirmation($allQuestion);
94
95
			if (!$allModels) {
96
				$modelQuestion = new Question('Which model');
97
				$modelQuestion->setAutocompleterValues($this->modelService->getModelNames());
98
				$model = $this->askQuestion($modelQuestion);
99
				$input->setOption('model', $model);
100
			}
101
			
102
		// ask question for a name
103
		} else if (!$generateModel) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
104
			// TODO: What to do here?
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
105
// 			$action = $this->getAction($name);
106
			
107
// 			// ask for classname
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
108
// 			$pkgClass = $action->getClass();
109
// 			$classname = $input->getOption('classname');
110
// 			if ($classname === null) {
111
// 				if (!empty($pkgClass)) {
112
// 					$classname = $pkgClass;
113
// 				} else {
114
// 					$classname = $this->guessClassname($name);
115
// 				}
116
// 			}
117
// 			$classname = $this->askQuestion(new Question('Classname', $classname));
118
// 			$input->setOption('classname', $classname);
119
120
		}
121
	}
122
123
	protected function execute(InputInterface $input, OutputInterface $output) {
124
		$this->preCheck();
125
		
126
		// 1. find out which action(s) to generate
127
		// 2. generate the information in the package
128
		// 3. generate the code for the action
129
		
130
		$name = $input->getArgument('name');
131
		$model = $input->getOption('model');
132
133
		// only a specific domain
134
		if ($name) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
135
// 			$this->generateAction($name);
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
136
		}
137
138
		// create action(s) from a model
139
		else if ($model) {
140
			$this->generateModel($model);
141
		}
142
143
		// anyway, generate all
144
		else {
145
			foreach ($this->modelService->getModels() as $model) {
146
				$modelName = $model->getOriginCommonName();
147
				$input->setOption('model', $modelName);
148
				$this->generateModel($modelName);
149
			}
150
		}
151
	}
152
153
	private function generateModel($modelName) {
154
		$this->logger->info('Generate Domain from Model: ' . $modelName);
155
		$model = $this->modelService->getModel($modelName);
156
		
157
		// generate class
158
		$generator = new DomainGenerator($this->service);
159
		$class = $generator->generate($model);
1 ignored issue
show
Bug introduced by
It seems like $model defined by $this->modelService->getModel($modelName) on line 155 can be null; however, keeko\tools\generator\do...inGenerator::generate() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
160
		$this->codegenService->dumpStruct($class, true);
161
		
162
		// generate trait
163
		$generator = $model->isReadOnly()
164
			? new ReadOnlyDomainTraitGenerator($this->service)
165
			: new DomainTraitGenerator($this->service);
166
		$trait = $generator->generate($model);
1 ignored issue
show
Bug introduced by
It seems like $model defined by $this->modelService->getModel($modelName) on line 155 can be null; however, keeko\tools\generator\do...itGenerator::generate() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
167
		$this->codegenService->dumpStruct($trait, true);
168
	}
169
170
	/**
171
	 * Generates a domain with trait for the given model
172
	 * 
173
	 * @TODO: Externalize this into its own command and call the command from here 
174
	 * 
175
	 * @param Table $model
176
	 */
177
	private function generateDomain(Table $model) {
178
		// generate class
179
		$generator = new DomainGenerator($this->service);
180
		$class = $generator->generate($model);
181
		$this->codegenService->dumpStruct($class, true);
182
		
183
		// generate trait
184
		$generator = $model->isReadOnly()
185
			? new ReadOnlyDomainTraitGenerator($this->service)
186
			: new DomainTraitGenerator($this->service);
187
		$trait = $generator->generate($model);
188
		$this->codegenService->dumpStruct($trait, true);
189
	}
190
	
191
// 	/**
192
// 	 * Generates an action.
193
// 	 *  
194
// 	 * @param string $actionName
195
// 	 * @param ActionSchema $action the action node from composer.json
196
// 	 */
197
// 	private function generateAction($actionName) {
198
// 		$this->logger->info('Generate Action: ' . $actionName);
199
// 		$input = $this->io->getInput();
200
		
201
// 		// get action and create it if it doesn't exist
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
202
// 		$action = $this->getAction($actionName);
203
		
204
// 		if (($title = $input->getOption('title')) !== null) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
205
// 			$action->setTitle($title);
206
// 		}
207
208
// 		if (Text::create($action->getTitle())->isEmpty()) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
61% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
209
// 			throw new \RuntimeException(sprintf('Cannot create action %s, because I am missing a title for it', $actionName));
210
// 		}
211
212
// 		if (($classname = $input->getOption('classname')) !== null) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
213
// 			$action->setClass($classname);
214
// 		}
215
		
216
// 		// guess classname if there is none set yet
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
217
// 		if (Text::create($action->getClass())->isEmpty()) {
218
// 			$action->setClass($this->guessClassname($actionName));
219
// 		}
220
		
221
// 		// guess title if there is none set yet
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
222
// 		if (Text::create($action->getTitle())->isEmpty() 
223
// 				&& $this->modelService->isModelAction($action)
224
// 				&& $this->modelService->isCrudAction($action)) {
225
// 			$modelName = $this->modelService->getModelNameByAction($action);
226
// 			$type = $this->modelService->getOperationByAction($action);
227
// 			$action->setTitle($this->getActionTitle($modelName, $type));
228
// 		}
229
		
230
// 		// set acl
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
231
// 		$action->setAcl($this->getAcl($action));
232
		
233
// 		// generate code
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
234
// 		$this->generateCode($action);
235
// 	}
236
	
237
// 	private function guessClassname($name) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
46% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
238
// 		$namespace = NamespaceResolver::getNamespace('src/action', $this->package);
239
// 		return $namespace . '\\' . NameUtils::toStudlyCase($name) . 'Action';
240
// 	}
241
	
242
}
243