Completed
Push — master ( 023239...2fb143 )
by Thomas
05:32 queued 50s
created

GenerateActionCommand   F

Complexity

Total Complexity 67

Size/Duplication

Total Lines 516
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 36

Test Coverage

Coverage 76.69%

Importance

Changes 20
Bugs 1 Features 2
Metric Value
wmc 67
c 20
b 1
f 2
lcom 1
cbo 36
dl 0
loc 516
ccs 181
cts 236
cp 0.7669
rs 1.3043

16 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 52 1
A initialize() 0 6 1
A preCheck() 0 6 2
C interact() 0 61 10
B execute() 0 42 4
B generateModel() 0 54 9
B getActionTitle() 0 13 7
A generateDomain() 0 5 1
A generateSerializer() 0 5 1
C generateAction() 0 39 8
A guessClassname() 0 4 1
A getAction() 0 9 2
C getAcl() 0 28 8
C generateCode() 0 63 8
B generateToOneRelationshipAction() 0 36 2
B generateToManyRelationshipAction() 0 40 2

How to fix   Complexity   

Complex Class

Complex classes like GenerateActionCommand often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use GenerateActionCommand, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace keeko\tools\command;
3
4
use gossi\codegen\model\PhpClass;
5
use gossi\codegen\model\PhpTrait;
6
use keeko\framework\schema\ActionSchema;
7
use keeko\framework\utils\NameUtils;
8
use keeko\tools\generator\action\BlankActionGenerator;
9
use keeko\tools\generator\action\NoopActionGenerator;
10
use keeko\tools\generator\action\ToManyRelationshipAddActionGenerator;
11
use keeko\tools\generator\action\ToManyRelationshipReadActionGenerator;
12
use keeko\tools\generator\action\ToManyRelationshipRemoveActionGenerator;
13
use keeko\tools\generator\action\ToManyRelationshipUpdateActionGenerator;
14
use keeko\tools\generator\action\ToOneRelationshipReadActionGenerator;
15
use keeko\tools\generator\action\ToOneRelationshipUpdateActionGenerator;
16
use keeko\tools\generator\GeneratorFactory;
17
use keeko\tools\helpers\QuestionHelperTrait;
18
use keeko\tools\utils\NamespaceResolver;
19
use phootwork\file\File;
20
use phootwork\lang\Text;
21
use Propel\Generator\Model\ForeignKey;
22
use Propel\Generator\Model\Table;
23
use Symfony\Component\Console\Input\InputArgument;
24
use Symfony\Component\Console\Input\InputInterface;
25 20
use Symfony\Component\Console\Input\InputOption;
26 20
use Symfony\Component\Console\Output\OutputInterface;
27 20
use Symfony\Component\Console\Question\ConfirmationQuestion;
28 20
use Symfony\Component\Console\Question\Question;
29 20
30 20
class GenerateActionCommand extends AbstractGenerateCommand {
31 20
32
	use QuestionHelperTrait;
33 20
	
34 20
	private $twig;
35 20
36 20
	protected function configure() {
37 20
		$this
38 20
			->setName('generate:action')
39
			->setDescription('Generates an action')
40 20
			->addArgument(
41 20
				'name',
42 20
				InputArgument::OPTIONAL,
43 20
				'The name of the action, which should be generated. Typically in the form %nomen%-%verb% (e.g. user-create)'
44 20
			)
45
			->addOption(
46 20
				'classname',
47 20
				'c',
48 20
				InputOption::VALUE_OPTIONAL,
49 20
				'The main class name (If ommited, class name will be guessed from action name)',
50 20
				null
51
			)
52 20
			->addOption(
53 20
				'model',
54 20
				'm',
55 20
				InputOption::VALUE_OPTIONAL,
56 20
				'The model for which the actions should be generated, when there is no name argument (if ommited all models will be generated)'
57
			)
58 20
			->addOption(
59 20
				'title',
60 20
				'',
61 20
				InputOption::VALUE_OPTIONAL,
62
				'The title for the generated option'
63 20
			)
64
			->addOption(
65
				'type',
66
				'',
67
				InputOption::VALUE_OPTIONAL,
68
				'The type of this action (list|create|read|update|delete) (if ommited template is guessed from action name)'
69
			)->addOption(
70
				'acl',
71 1
				'',
72
				InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL,
73 20
				'The acl\s for this action (guest, user and/or admin)'
74
			)
75 20
// 			->addOption(
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% 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...
76 20
// 				'schema',
77
// 				's',
78
// 				InputOption::VALUE_OPTIONAL,
79
// 				'Path to the database schema (if ommited, database/schema.xml is used)',
80
// 				null
81
// 			)
82 10
		;
83 10
		
84 10
		$this->configureGenerateOptions();
85 1
		
86 4
		parent::configure();
87 9
	}
88
89
	protected function initialize(InputInterface $input, OutputInterface $output) {
90
		parent::initialize($input, $output);
91
92
		$loader = new \Twig_Loader_Filesystem($this->service->getConfig()->getTemplateRoot() . '/actions');
93
		$this->twig = new \Twig_Environment($loader);
94
	}
95
96
	/**
97
	 * Checks whether actions can be generated at all by reading composer.json and verify
98
	 * all required information are available
99
	 */
100
	private function preCheck() {
101
		$module = $this->packageService->getModule();
102
		if ($module === null) {
103
			throw new \DomainException('No module definition found in composer.json - please run `keeko init`.');
104
		}
105
	}
106
	
107
	protected function interact(InputInterface $input, OutputInterface $output) {
108
		$this->preCheck();
109
		
110
		// check if the dialog can be skipped
111
		$name = $input->getArgument('name');
112
		$model = $input->getOption('model');
113
		
114
		if ($model !== null) {
115
			return;
116
		} else if ($name !== null) {
117
			$generateModel = false;
118
		} else {
119
			$modelQuestion = new ConfirmationQuestion('Do you want to generate an action based off a model?');
120
			$generateModel = $this->askConfirmation($modelQuestion);
121
		}
122
		
123
		// ask questions for a model
124
		if ($generateModel) {
125
			$schema = str_replace(getcwd(), '', $this->modelService->getSchema());
126
			$allQuestion = new ConfirmationQuestion(sprintf('For all models in the schema (%s)?', $schema));
127
			$allModels = $this->askConfirmation($allQuestion);
128
129
			if (!$allModels) {
130
				$modelQuestion = new Question('Which model');
131
				$modelQuestion->setAutocompleterValues($this->modelService->getModelNames());
132
				$model = $this->askQuestion($modelQuestion);
133
				$input->setOption('model', $model);
134
			}
135
		} else if (!$generateModel) {
136
			$action = $this->getAction($name);
137
			
138
			// ask for title
139
			$pkgTitle = $action->getTitle();
140
			$title = $input->getOption('title');
141
			if ($title === null && !empty($pkgTitle)) {
142
				$title = $pkgTitle;
143
			}
144
			$titleQuestion = new Question('What\'s the title for your action?', $title);
145
			$title = $this->askQuestion($titleQuestion);
146
			$input->setOption('title', $title);
147
			
148
			// ask for classname
149
			$pkgClass = $action->getClass();
150
			$classname = $input->getOption('classname');
151
			if ($classname === null) {
152 10
				if (!empty($pkgClass)) {
153 10
					$classname = $pkgClass;
154
				} else {
155
					$classname = $this->guessClassname($name);
156
				}
157
			}
158
			$classname = $this->askQuestion(new Question('Classname', $classname));
159 9
			$input->setOption('classname', $classname);
160 9
			
161
			// ask for acl
162
			$acls = $this->getAcl($action);
163 9
			$aclQuestion = new Question('ACL (comma separated list, with these options: guest, user, admin)', implode(', ', $acls));
164 3
			$acls = $this->askQuestion($aclQuestion);
165 2
			$input->setOption('acl', $acls);
166
		}
167
	}
168 6
169 2
	protected function execute(InputInterface $input, OutputInterface $output) {
170 2
		$this->preCheck();
171
		
172
		// 1. find out which action(s) to generate
173 4
		// 2. generate the information in the package
174 3
		// 3. generate the code for the action
175 3
		
176 2
		$name = $input->getArgument('name');
177 2
		$model = $input->getOption('model');
178 2
179 1
		// only a specific action
180
		if ($name) {
181 3
			$this->generateAction($name);
182
		}
183
184
		// create action(s) from a model
185 1
		else if ($model) {
186 1
			$this->generateModel($model);
187 1
		}
188
		
189
		// if this is a core-module, find the related model
190 8
// 		else /*if ($this->package->getVendor() == 'keeko' && $this->modelService->isCoreSchema()) */ {
191 8
// 			$model = $this->package->getName();
192
// 			if ($this->modelService->hasModel($model)) {
193 5
// 				$input->setOption('model', $model);
194 5
// 				$this->generateModel($model);
195 5
// 			} else {
196 5
// 				$this->logger->error('Tried to find model on my own, wasn\'t lucky - please provide model with the --model option');
197 5
// 			}
198 1
// 		}
199 1
200 4
		// anyway, generate all
201
		else {
202
			foreach ($this->modelService->getModels() as $model) {
203 5
				$modelName = $model->getOriginCommonName();
204 5
				$input->setOption('model', $modelName);
205 5
				$this->generateModel($modelName);
206 5
			}
207 5
		}
208 5
		
209 4
		$this->packageService->savePackage();
210 5
	}
211 5
212 5
	private function generateModel($modelName) {
213
		$this->logger->info('Generate Action from Model: ' . $modelName);
214 5
		$input = $this->io->getInput();
215 5
		$model = $this->modelService->getModel($modelName);
216
		
217 4
		// generate domain + serializer
218
		$this->generateDomain($model);
1 ignored issue
show
Bug introduced by
It seems like $model defined by $this->modelService->getModel($modelName) on line 215 can be null; however, keeko\tools\command\Gene...mmand::generateDomain() 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...
219 4
		$this->generateSerializer($model);
1 ignored issue
show
Bug introduced by
It seems like $model defined by $this->modelService->getModel($modelName) on line 215 can be null; however, keeko\tools\command\Gene...d::generateSerializer() 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...
220 3
221
		// generate action type(s)
222 4
		$typeDump = $input->getOption('type');
223 4
		if ($typeDump !== null) {
224 4
			$types = [$typeDump];
225 4
		} else {
226 4
			$types = ['create', 'read', 'list', 'update', 'delete'];
227
		}
228
		
229
		foreach ($types as $type) {
230
			$input->setOption('acl', ['admin']);
1 ignored issue
show
Documentation introduced by
array('admin') is of type array<integer,string,{"0":"string"}>, but the function expects a string|boolean.

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...
231
			$input->setOption('type', $type);
232
			$actionName = $modelName . '-' . $type;
233
			
234
			if ($model->isReadOnly() && in_array($type, ['create', 'update', 'delete'])) {
235
				$this->logger->info(sprintf('Skip generate Action (%s), because Model (%s) is read-only', $actionName, $modelName));
236
				continue;
237 8
			}
238 8
			
239 8
			$action = $this->getAction($actionName);
240
			if (Text::create($action->getTitle())->isEmpty()) {
241
				$action->setTitle($this->getActionTitle($modelName, $type));
242 8
			}
243
			$this->generateAction($actionName);
244 8
		}
245 2
		
246 2
		// generate relationship actions
247
		if (!$model->isReadOnly()) {
248 8
			$relationships = $this->modelService->getRelationships($model);
1 ignored issue
show
Bug introduced by
It seems like $model defined by $this->modelService->getModel($modelName) on line 215 can be null; however, keeko\tools\services\Mod...ice::getRelationships() 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...
249 1
				
250
			// to-one relationships
251
			foreach ($relationships['one'] as $one) {
252 7
				$fk = $one['fk'];
253 2
				$this->generateToOneRelationshipAction($model, $fk->getForeignTable(), $fk);
1 ignored issue
show
Bug introduced by
It seems like $model defined by $this->modelService->getModel($modelName) on line 215 can be null; however, keeko\tools\command\Gene...OneRelationshipAction() 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...
254 2
			}
255
			
256
			// to-many relationships
257 7
			foreach ($relationships['many'] as $many) {
258 4
				$fk = $many['fk'];
259 4
				$cfk = $many['cfk'];
260
				$this->generateToManyRelationshipAction($model, $fk->getForeignTable(), $cfk->getMiddleTable());
1 ignored issue
show
Bug introduced by
It seems like $model defined by $this->modelService->getModel($modelName) on line 215 can be null; however, keeko\tools\command\Gene...anyRelationshipAction() 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...
261
			}
262 7
		}
263 7
		
264 7
		$input->setOption('type', $typeDump);
265
	}
266
267
	private function getActionTitle($modelName, $type) {
268
		$name = NameUtils::dasherize($modelName);
1 ignored issue
show
Bug introduced by
The method dasherize() cannot be called from this context as it is declared private in class keeko\framework\utils\NameUtils.

This check looks for access to methods that are not accessible from the current context.

If you need to make a method accessible to another context you can raise its visibility level in the defining class.

Loading history...
269
		switch ($type) {
270
			case 'list':
271 7
				return 'List all ' . NameUtils::pluralize($name);
272
273
			case 'create':
274 7
			case 'read':
275 7
			case 'update':
276
			case 'delete':
277 4
				return ucfirst($type) . 's ' . (in_array($name[0], ['a', 'e', 'i', 'o', 'u']) ? 'an' : 'a') . ' ' . $name;
278 4
		}
279 4
	}
280
281
	/**
282
	 * Generates a domain with trait for the given model
283
	 * 
284
	 * @param Table $model
285
	 */
286
	private function generateDomain(Table $model) {
287 8
		$this->runCommand('generate:domain', [
288 8
			'--model' => $model->getOriginCommonName()
289 8
		]);
290 7
	}
291 7
	
292 7
	/**
293 7
	 * Generates a serializer for the given model
294 8
	 *
295
	 * @param Table $model
296
	 */
297 7
	private function generateSerializer(Table $model) {
298 7
		$this->runCommand('generate:serializer', [
299 7
			'--model' => $model->getOriginCommonName()
300 7
		]);
301 7
	}
302 2
	
303 2
	/**
304 7
	 * Generates an action.
305 7
	 *  
306 1
	 * @param string $actionName
307 1
	 * @param ActionSchema $action the action node from composer.json
0 ignored issues
show
Documentation introduced by
There is no parameter named $action. Did you maybe mean $actionName?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
308 1
	 */
309 1
	private function generateAction($actionName) {
310 1
		$this->logger->info('Generate Action: ' . $actionName);
311 6
		$input = $this->io->getInput();
312
		
313 7
		// get action and create it if it doesn't exist
314
		$action = $this->getAction($actionName);
315 7
		
316
		if (($title = $input->getOption('title')) !== null) {
317
			$action->setTitle($title);
318
		}
319
320
		if (Text::create($action->getTitle())->isEmpty()) {
321
			throw new \RuntimeException(sprintf('Cannot create action %s, because I am missing a title for it', $actionName));
322
		}
323
324
		if (($classname = $input->getOption('classname')) !== null) {
325
			$action->setClass($classname);
326
		}
327
		
328
		// guess classname if there is none set yet
329
		if (Text::create($action->getClass())->isEmpty()) {
330
			$action->setClass($this->guessClassname($actionName));
331 7
		}
332 7
		
333 7
		// guess title if there is none set yet
334
		if (Text::create($action->getTitle())->isEmpty() 
335
				&& $this->modelService->isModelAction($action)
336 7
				&& $this->modelService->isCrudAction($action)) {
337 7
			$modelName = $this->modelService->getModelNameByAction($action);
338 7
			$type = $this->modelService->getOperationByAction($action);
339 7
			$action->setTitle($this->getActionTitle($modelName, $type));
340 7
		}
341
		
342
		// set acl
343 7
		$action->setAcl($this->getAcl($action));
344
		
345 1
		// generate code
346 1
		$this->generateCode($action);
347
	}
348 1
	
349 1
	private function guessClassname($name) {
350 1
		$namespace = NamespaceResolver::getNamespace('src/action', $this->package);
351
		return $namespace . '\\' . NameUtils::toStudlyCase($name) . 'Action';
352
	}
353 1
	
354 1
	/**
355 1
	 * 
356
	 * @param string $actionName
357
	 * @return ActionSchema
358
	 */
359 6
	private function getAction($actionName) {
360 6
		$action = $this->packageService->getAction($actionName);
361 6
		if ($action == null) {
362 6
			$action = new ActionSchema($actionName);
363 6
			$module = $this->packageService->getModule();
364
			$module->addAction($action);
365
		}
366
		return $action;
367 7
	}
368 5
	
369 1
	private function getAcl(ActionSchema $action) {
370 1
		$acls = [];
371 1
		$acl = $this->io->getInput()->getOption('acl');
372 5
		if ($acl !== null && count($acl) > 0) {
373 5
			if (!is_array($acl)) {
374
				$acl = [$acl];
375 5
			}
376 5
			foreach ($acl as $group) {
377
				if (strpos($group, ',') !== false) {
378 5
					$groups = explode(',', $group);
379 4
					foreach ($groups as $g) {
380 4
						$acls[] = trim($g);
381 4
					}
382 5
				} else {
383
					$acls[] = $group;
384 2
				}
385 2
			}
386 2
			
387 2
			return $acls;
388 2
		}
389
		
390
		// read default from package
391 7
		if (!$action->getAcl()->isEmpty()) {
392 7
			return $action->getAcl()->toArray();
393
		}
394
395
		return $acls;
396
	}
397
	
398
	/**
399
	 * Generates code for an action
400
	 * 
401
	 * @param ActionSchema $action
402
	 */
403
	private function generateCode(ActionSchema $action) {
404
		$input = $this->io->getInput();
405
		$trait = null;
0 ignored issues
show
Unused Code introduced by
$trait is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
406
407
		// class
408
		$class = new PhpClass($action->getClass());
409
		$filename = $this->codegenService->getFilename($class);
410
		$traitNs = $class->getNamespace() . '\\base';
411
		$traitName = $class->getName() . 'Trait';
412
		$overwrite = false;
413
		
414
		// load from file, when class exists
415
		if (file_exists($filename)) {
416
			// load trait
417
			$trait = new PhpTrait($traitNs . '\\' . $traitName);
418
			$traitFile = new File($this->codegenService->getFilename($trait));
419
420
			if ($traitFile->exists()) {
421
				$trait = PhpTrait::fromFile($traitFile->getPathname());
0 ignored issues
show
Unused Code introduced by
$trait is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
422
			}
423
		
424
			// load class
425
			$class = PhpClass::fromFile($filename);
426
		}
427
		
428
		// anyway seed class information
429
		else {
430
			$overwrite = true;
431
			$class->setParentClassName('AbstractAction');
432
			$class->setDescription($action->getTitle());
433
			$class->setLongDescription($action->getDescription());
434
			$this->codegenService->addAuthors($class, $this->package);
435
		}
436
		
437
		// create base trait
438
		$modelName = $input->getOption('model');
439
		if ($modelName !== null) {
440
			$type = $this->packageService->getActionType($action->getName(), $modelName);
441
			$generator = GeneratorFactory::createActionTraitGenerator($type, $this->service);
442
			$trait = $generator->generate($traitNs . '\\' . $traitName, $action);
443
444
			$this->codegenService->addAuthors($trait, $this->package);
445
			$this->codegenService->dumpStruct($trait, true);
446
			
447
			if (!$class->hasTrait($trait)) {
448
				$class->addTrait($trait);
449
				$overwrite = true;
450
			}
451
		}
452
		
453
		// create class generator
454
		if ($modelName === null && !$class->hasMethod('run')) {
455
			$overwrite = true;
456
			$generator = new BlankActionGenerator($this->service);
457
		} else {
458
			$generator = new NoopActionGenerator($this->service);
459
		}
460
461
		$class = $generator->generate($class);
462
		$overwrite = $overwrite || $input->getOption('force');
463
464
		$this->codegenService->dumpStruct($class, $overwrite);
465
	}
466
	
467
	private function generateToOneRelationshipAction(Table $model, Table $foreign, ForeignKey $fk) {
468
		$module = $this->package->getKeeko()->getModule();
469
		$fkModelName = $foreign->getPhpName();
470
		$actionNamePrefix = sprintf('%s-to-%s-relationship', $model->getOriginCommonName(), $foreign->getOriginCommonName());
471
	
472
		$generators = [
473
			'read' => new ToOneRelationshipReadActionGenerator($this->service),
474
			'update' => new ToOneRelationshipUpdateActionGenerator($this->service)
475
		];
476
		$titles = [
477
			'read' => 'Reads the relationship of {model} to {foreign}',
478
			'update' => 'Updates the relationship of {model} to {foreign}'
479
		];
480
	
481
		foreach (array_keys($generators) as $type) {
482
			// generate fqcn
483
			$className = sprintf('%s%s%sAction', $model->getPhpName(), $fkModelName, ucfirst($type));
484
			$fqcn = $this->packageService->getNamespace() . '\\action\\' . $className;
485
	
486
			// generate action
487
			$action = new ActionSchema($actionNamePrefix . '-' . $type);
488
			$action->addAcl('admin');
489
			$action->setClass($fqcn);
490
			$action->setTitle(str_replace(
491
				['{model}', '{foreign}'],
492
				[$model->getOriginCommonName(), $foreign->getoriginCommonName()],
493
				$titles[$type])
494
			);
495
			$module->addAction($action);
496
	
497
			// generate class
498
			$generator = $generators[$type];
499
			$class = $generator->generate(new PhpClass($fqcn), $model, $foreign, $fk);
500
			$this->codegenService->dumpStruct($class, true);
501
		}
502
	}
503
	
504
	private function generateToManyRelationshipAction(Table $model, Table $foreign, Table $middle) {
505
		$module = $this->package->getKeeko()->getModule();
506
		$fkModelName = $foreign->getPhpName();
507
		$actionNamePrefix = sprintf('%s-to-%s-relationship', $model->getOriginCommonName(), $foreign->getOriginCommonName());
508
		
509
		$generators = [
510
			'read' => new ToManyRelationshipReadActionGenerator($this->service),
511
			'update' => new ToManyRelationshipUpdateActionGenerator($this->service),
512
			'add' => new ToManyRelationshipAddActionGenerator($this->service),
513
			'remove' => new ToManyRelationshipRemoveActionGenerator($this->service)
514
		];
515
		$titles = [
516
			'read' => 'Reads the relationship of {model} to {foreign}',
517
			'update' => 'Updates the relationship of {model} to {foreign}',
518
			'add' => 'Adds {foreign} as relationship to {model}',
519
			'remove' => 'Removes {foreign} as relationship of {model}'
520
		];
521
	
522
		foreach (array_keys($generators) as $type) {
523
			// generate fqcn
524
			$className = sprintf('%s%s%sAction', $model->getPhpName(), $fkModelName, ucfirst($type));
525
			$fqcn = $this->packageService->getNamespace() . '\\action\\' . $className;
526
	
527
			// generate action
528
			$action = new ActionSchema($actionNamePrefix . '-' . $type);
529
			$action->addAcl('admin');
530
			$action->setClass($fqcn);
531
			$action->setTitle(str_replace(
532
				['{model}', '{foreign}'],
533
				[$model->getOriginCommonName(), $foreign->getoriginCommonName()],
534
				$titles[$type])
535
			);
536
			$module->addAction($action);
537
	
538
			// generate class
539
			$generator = $generators[$type];
540
			$class = $generator->generate(new PhpClass($fqcn), $model, $foreign, $middle);
541
			$this->codegenService->dumpStruct($class, true);
542
		}
543
	}
544
545
}
546