Completed
Push — master ( dd800d...af5658 )
by Thomas
07:26
created

GenerateSerializerCommand::interact()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 0
loc 6
rs 9.4285
cc 1
eloc 4
nc 1
nop 2
1
<?php
2
namespace keeko\tools\command;
3
4
use gossi\codegen\model\PhpClass;
5
use gossi\codegen\model\PhpMethod;
6
use gossi\codegen\model\PhpProperty;
7
use keeko\tools\generator\serializer\base\ModelSerializerTraitGenerator;
8
use keeko\tools\generator\serializer\ModelSerializerGenerator;
9
use keeko\tools\generator\serializer\SkeletonSerializerGenerator;
10
use keeko\tools\helpers\QuestionHelperTrait;
11
use keeko\tools\ui\SerializerUI;
12
use keeko\tools\utils\NamespaceResolver;
13
use phootwork\lang\Text;
14
use phpDocumentor\Reflection\DocBlock\Serializer;
15
use Symfony\Component\Console\Input\InputArgument;
16
use Symfony\Component\Console\Input\InputInterface;
17
use Symfony\Component\Console\Input\InputOption;
18
use Symfony\Component\Console\Output\OutputInterface;
19
20
class GenerateSerializerCommand extends AbstractKeekoCommand {
21
22
	use QuestionHelperTrait;
23
	
24
	private $twig;
25
26
	protected function configure() {
27
		$this
28
			->setName('generate:serializer')
29
			->setDescription('Generates a serializer')
30
			->addArgument(
31
				'name',
32
				InputArgument::OPTIONAL,
33
				'The name of the action for which the serializer should be generated.'
34
			)
35
			->addOption(
36
				'model',
37
				'm',
38
				InputOption::VALUE_OPTIONAL,
39
				'The model for which the serializer should be generated, when there is no name argument (if ommited all models will be generated)'
40
			)
41
		;
42
		
43
		$this->configureGenerateOptions();
44
		
45
		parent::configure();
46
	}
47
48
	protected function initialize(InputInterface $input, OutputInterface $output) {
49
		parent::initialize($input, $output);
50
51
		$loader = new \Twig_Loader_Filesystem($this->service->getConfig()->getTemplateRoot() . '/serializer');
52
		$this->twig = new \Twig_Environment($loader);
53
	}
54
55
	/**
56
	 * Checks whether actions can be generated at all by reading composer.json and verify
57
	 * all required information are available
58
	 */
59
	private function preCheck() {
60
		$module = $this->packageService->getModule();
61
		if ($module === null) {
62
			throw new \DomainException('No module definition found in composer.json - please run `keeko init`.');
63
		}
64
	}
65
	
66
	protected function interact(InputInterface $input, OutputInterface $output) {
67
		$this->preCheck();
68
		
69
		$ui = new SerializerUI($this);
70
		$ui->show();
71
	}
72
73
	protected function execute(InputInterface $input, OutputInterface $output) {
74
		$this->preCheck();
75
		
76
		$name = $input->getArgument('name');
77
		$model = $input->getOption('model');
78
79
		// only a specific action
80
		if ($name) {
81
			$this->generateSkeleton($name);
82
		}
83
84
		// create action(s) from a model
85
		else if ($model) {
86
			$this->generateModel($model);
87
		}
88
89
		// anyway, generate all models
90
		else {
91
			foreach ($this->modelService->getModels() as $model) {
92
				$modelName = $model->getOriginCommonName();
93
				$input->setOption('model', $modelName);
94
				$this->generateModel($modelName);
95
			}
96
		}
97
	}
98
99
	private function generateModel($modelName) {
100
		$this->logger->info('Generate Serializer from Model: ' . $modelName);
101
		$model = $this->modelService->getModel($modelName);
102
		
103
		// generate class
104
		$generator = new ModelSerializerGenerator($this->service);
105
		$serializer = $generator->generate($model);
106
		$this->codegenService->dumpStruct($serializer, true);
107
		
108
		// generate trait
109
		$generator = new ModelSerializerTraitGenerator($this->service);
110
		$trait = $generator->generate($model);
111
		$this->codegenService->dumpStruct($trait, true);
112
		
113
		// add serializer + ApiModelInterface on the model
114
		$class = new PhpClass(str_replace('\\\\', '\\', $model->getNamespace() . '\\' . $model->getPhpName()));
115
		$file = $this->codegenService->getFile($class);
116
		if ($file->exists()) {
117
			$class = PhpClass::fromFile($this->codegenService->getFilename($class));
118
			$class
119
				->addUseStatement($serializer->getQualifiedName())
120
				->addUseStatement('keeko\\framework\\model\\ApiModelInterface')
121
				->addInterface('ApiModelInterface')
122
				->setProperty(PhpProperty::create('serializer')
123
					->setStatic(true)
124
					->setVisibility('private')
125
				)
126
				->setMethod(PhpMethod::create('getSerializer')
127
					->setStatic(true)
128
					->setType($serializer->getName())
129
					->setBody($this->twig->render('get-serializer.twig', [
130
						'class' => $serializer->getName()
131
					]))
132
				)
133
			;
134
		
135
			$this->codegenService->dumpStruct($class, true);
136
		}
137
	}
138
	
139
	/**
140
	 * Generates a skeleton serializer
141
	 *  
142
	 * @param string $name
143
	 */
144
	private function generateSkeleton($name) {
145
		$this->logger->info('Generate Skeleton Serializer: ' . $name);
146
		$input = $this->io->getInput();
147
148
		$className = NamespaceResolver::getNamespace('src/serializer', $this->package) . '\\' . $name;
149
		
150
		if (!Text::create($className)->endsWith('Serializer')) {
151
			$className .= 'Serializer';
152
		}
153
154
		// generate code
155
		$generator = new SkeletonSerializerGenerator($this->service);
156
		$class = $generator->generate($className);
157
		$this->codegenService->dumpStruct($class, $input->getOption('force'));
158
	}
159
	
160
	
161
162
}
163