Completed
Push — master ( af5658...fe61ae )
by Thomas
06:08
created

InitCommand   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 207
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 14

Test Coverage

Coverage 41.78%

Importance

Changes 14
Bugs 1 Features 1
Metric Value
wmc 30
c 14
b 1
f 1
lcom 1
cbo 14
dl 0
loc 207
ccs 61
cts 146
cp 0.4178
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 64 1
A initialize() 0 3 1
A getPackage() 0 3 1
A getIO() 0 3 1
A interact() 0 4 1
A execute() 0 4 1
F generatePackage() 0 80 20
A manageDependencies() 0 19 3
A generateCode() 0 8 1
1
<?php
2
namespace keeko\tools\command;
3
4
use keeko\framework\schema\AuthorSchema;
5
use keeko\tools\generator\GeneratorFactory;
6
use keeko\tools\helpers\InitCommandHelperTrait;
7
use keeko\tools\services\IOService;
8
use keeko\tools\ui\InitUI;
9
use Symfony\Component\Console\Input\InputInterface;
10
use Symfony\Component\Console\Input\InputOption;
11
use Symfony\Component\Console\Output\OutputInterface;
12
13
class InitCommand extends AbstractKeekoCommand {
14
	
15
	use InitCommandHelperTrait;
16
17
	protected function configure() {
18
		$this
19
			->setName('init')
20
			->setDescription('Initializes composer.json with keeko related values')
21
			->addOption(
22
				'name',
23
				'',
24
				InputOption::VALUE_REQUIRED,
25 20
				'Name of the package'
26 20
			)
27 20
			->addOption(
28 20
				'description',
29 20
				'd',
30 20
				InputOption::VALUE_OPTIONAL,
31 20
				'Description of the package'
32 20
			)
33
			->addOption(
34 20
				'author',
35 20
				'',
36 20
				InputOption::VALUE_OPTIONAL,
37 20
				'Author name of the package'
38 20
			)
39
			->addOption(
40 20
				'type',
41 20
				't',
42 20
				InputOption::VALUE_REQUIRED,
43 20
				'The type of the package (app|module)'
44 20
			)
45
			->addOption(
46 20
				'namespace',
47 20
				'ns',
48 20
				InputOption::VALUE_OPTIONAL,
49 20
				'The package\'s namespace for the src/ folder (If ommited, the package name is used)'
50 20
			)
51
			->addOption(
52 20
				'license',
53 20
				'l',
54 20
				InputOption::VALUE_OPTIONAL,
55 20
				'License of the package'
56 20
			)
57
			->addOption(
58 20
				'title',
59 20
				'',
60 20
				InputOption::VALUE_OPTIONAL,
61 20
				'The package\'s title (If ommited, second part of the package name is used)',
62 20
				null
63
			)
64 20
			->addOption(
65 20
				'classname',
66 20
				'c',
67 20
				InputOption::VALUE_OPTIONAL,
68 20
				'The main class name (If ommited, there is a default handler)',
69 20
				null
70
			)
71 20
			->addOption(
72 20
				'force',
73 20
				'f',
74 20
				InputOption::VALUE_NONE,
75 20
				'Allows to overwrite existing values'
76 20
			)
77
		;
78 20
		
79
		$this->configureGlobalOptions();
80
	}
81
82
	protected function initialize(InputInterface $input, OutputInterface $output) {
83
		parent::initialize($input, $output);
84
	}
85 20
	
86 20
	/**
87 20
	 * @return PackageSchema
88 20
	 */
89
	protected function getPackage() {
90 20
		return $this->package;
91 20
	}
92 20
	
93 20
	/**
94 20
	 * @return IOService
95
	 */
96 20
	protected function getIO() {
97
		return $this->io;
98
	}
99 20
100 20
	protected function interact(InputInterface $input, OutputInterface $output) {
101
		$ui = new InitUI($this);
102 3
		$ui->show();
103 3
	}
104 3
105
	protected function execute(InputInterface $input, OutputInterface $output) {
106
		$this->generatePackage();
107
		$this->generateCode();
108
	}
109
	
110
	private function generatePackage() {
111
		$input = $this->io->getInput();
112
		$force = $input->getOption('force');
113
114
		// name
115
		$localName = $this->package->getFullName();
116
		if (empty($localName) && $input->getOption('name') === null) {
117
			throw new \RuntimeException('No name for the package given');
118
		}
119
		
120
		if (($force || empty($localName)) && ($name = $input->getOption('name')) !== null) {
121
			$this->validateName($name);
122
			$this->package->setFullName($name);
123
		}
124
		
125
		// description
126
		if (($desc = $input->getOption('description')) !== null) {
127
			$this->package->setDescription($desc);
128
		}
129
		
130
		// type
131
		if (($type = $input->getOption('type')) !== null) {
132
			if (in_array($type, ['app', 'module'])) {
133
				$this->package->setType('keeko-' . $type);
134
			}
135
		}
136
		
137
		// license
138
		if (($license = $input->getOption('license')) !== null) {
139
			$this->package->setLicense($license);
140
		}
141
		
142
		// author
143
		if (($author = $input->getOption('author')) !== null
144
				&& ($this->package->getAuthors()->isEmpty() || $force)) {
145
			list($name, $email) = sscanf($author, '%s <%s>');
146
		
147
			$author = new AuthorSchema();
148
			$author->setName($name);
149
		
150
			if (substr($email, -1) == '>') {
151
				$email = substr($email, 0, -1);
152
			}
153
			$author->setEmail($email);
154
				
155
			$this->package->getAuthors()->add($author);
156
		}
157
158
		// autoload
159
		if (!$this->hasAutoload()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->hasAutoload() of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
160
			$namespace = $input->getOption('namespace');
161
			if ($namespace === null) {
162
				$namespace = str_replace('/', '\\', $this->package->getFullName());
163
			}
164
			if (substr($namespace, -2) !== '\\') {
165
				$namespace .= '\\';
166
			}
167
			$this->setAutoload($namespace);
168
		}
169
		
170
		$this->manageDependencies();
171
		
172
		// KEEKO
173
		if ($type === null) {
174
			$type = $this->getPackageType();
175
		}
176
		
177
		// title
178
		$keeko = $this->packageService->getKeeko()->getKeekoPackage($type);
179
		if (($title = $this->getPackageTitle()) !== null) {
180
			$keeko->setTitle($title);
181
		}
182
		
183
		// class
184
		if (($classname = $this->getPackageClass()) !== null) {
185
			$keeko->setClass($classname);
186
		}
187
		
188
		$this->packageService->savePackage($this->package);
189
	}
190
191
	private function manageDependencies() {
192
		// add require statements
193
		$require = $this->package->getRequire();
194
195
		if (!$require->has('php')) {
196
			$require->set('php', '>=5.4');
197
		}
198
199
		if (!$require->has('keeko/composer-installer')) {
200
			$require->set('keeko/composer-installer', '*');
201
		}
202
203
		// add require dev statements
204
		$requireDev = $this->package->getRequireDev();
205
		$requireDev->set('keeko/core', 'dev-master');
206
		$requireDev->set('composer/composer', '@dev');
207
		$requireDev->set('propel/propel', '@dev');
208
		$requireDev->set('puli/composer-plugin', '@beta');
209
	}
210
211
	private function generateCode() {
212
		$type = $this->getPackageType();
213
		$package = $this->package->getKeeko()->getKeekoPackage($type);
214
		$generator = GeneratorFactory::createPackageGenerator($type, $this->service);
215
		$class = $generator->generate($package);
1 ignored issue
show
Bug introduced by
It seems like $package defined by $this->package->getKeeko...>getKeekoPackage($type) on line 213 can also be of type null; however, keeko\tools\generator\pa...geGenerator::generate() does only seem to accept object<keeko\framework\schema\KeekoPackageSchema>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
216
217
		$this->codegenService->dumpStruct($class, true);
218
	}
219
}
220