Bootstrap::terminate()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
4
namespace Genesis;
5
6
7
use Genesis\Config\Container;
8
use Genesis\Config\ContainerFactory;
9
10
/**
11
 * @author Adam Bisek <[email protected]>
12
 */
13
class Bootstrap
14
{
15
16
	const DEFAULT_CONFIG_FILE = 'config.neon';
17
18
	/** @var BuildFactory */
19
	private $buildFactory;
20
21
	/** @var string */
22
	private $workingDir;
23
24
25
	/**
26
	 * @return BuildFactory
27
	 */
28 1
	public function getBuildFactory()
29 1
	{
30
		return $this->buildFactory;
31
	}
32
33
34
	/**
35
	 * @param BuildFactory $buildFactory
36
	 */
37 14
	public function setBuildFactory($buildFactory)
38
	{
39 14
		$this->buildFactory = $buildFactory;
40 14
	}
41
42
43
	/**
44
	 * @param InputArgs $inputArgs
45
	 * @throws TerminateException
46
	 */
47 14
	public function run(InputArgs $inputArgs)
48
	{
49 14
		$this->startup($inputArgs);
50 13
		$this->selfInit($inputArgs);
51 12
		$arguments = $inputArgs->getArguments();
52 12
		$container = $this->resolveBootstrap();
53 11
		$configFile = $inputArgs->getOption('config') ? $inputArgs->getOption('config') : self::DEFAULT_CONFIG_FILE;
54
		try {
55 11
			$container = $this->createContainer($configFile, $container);
56 11
			$build = $this->createBuild($container, $arguments);
57 11
		} catch (\Throwable $e) { // fault barrier -> catch all
58
			$this->handleException($e);
59 2
		} catch (\Exception $e) { // fault barrier -> catch all, PHP 5.x compatibility
60 2
			$this->handleException($e);
61
		}
62 9
		if (count($arguments) < 1) {
63 2
			$this->invokeTask($build, 'default', $arguments);
64 2
			$this->terminate(0);
65
		}
66
67
		try {
68 7
			$this->invokeTask($build, $arguments[0], $arguments);
69 7
		} catch (TerminateException $e) {
70 3
			throw $e; // rethrow -> shutdown imminent
71 1
		} catch (\Throwable $e) { // fault barrier -> catch all
72
			$this->handleException($e);
73 1
		} catch (\Exception $e) { // fault barrier -> catch all, PHP 5.x compatibility
74 1
			$this->handleException($e);
75
		}
76 5
		$this->log("Exited with SUCCESS", 'black', 'green');
77 5
		echo PHP_EOL;
78 5
		$this->terminate(0);
79
	}
80
81
82 14
	private function terminate($code)
83
	{
84 14
		throw new TerminateException(NULL, $code);
85 1
	}
86
87
88 14
	private function startup(InputArgs $inputArgs)
89
	{
90 14
		$this->workingDir = getcwd();
91 14
		if ($inputArgs->getOption('colors') !== NULL && !$inputArgs->getOption('colors')) {
92 14
			Cli::$enableColors = FALSE;
93 14
		}
94 14
		if ($inputArgs->getOption('working-dir')) {
95 14
			$this->workingDir = realpath($inputArgs->getOption('working-dir'));
96 14
			if (!$this->workingDir) {
97 1
				$this->log(sprintf("Working dir '%s' does not exists.", $inputArgs->getOption('working-dir')), 'red');
98 2
				$this->terminate(255);
99
			}
100 14
		}
101 14
		if ($this->workingDir === __DIR__) {
102 1
			$this->log(sprintf("Working dir '%s' is directory with Genesis. You have to choose directory with build.", $this->workingDir), 'red');
103 1
			$this->terminate(255);
104
		}
105 13
	}
106
107
108 13
	private function selfInit(InputArgs $inputArgs)
109
	{
110 13
		$arguments = $inputArgs->getArguments();
111 13
		if (isset($arguments[0]) && $arguments[0] === 'self-init') {
112 1
			$directoryName = isset($arguments[1]) ? $arguments[1] : 'build';
113 1
			$selfInit = new Commands\SelfInit();
114 1
			$selfInit->setDistDirectory(__DIR__ . '/build-dist');
115 1
			$selfInit->setWorkingDirectory($this->workingDir);
116 1
			$selfInit->setDirname($directoryName);
117 1
			$selfInit->execute();
118 1
			$this->terminate(0);
119
		}
120 12
	}
121
122
123
	/**
124
	 * @return Container|NULL
125
	 */
126 12
	private function resolveBootstrap()
127
	{
128 12
		$bootstrapFile = $this->workingDir . DIRECTORY_SEPARATOR . 'bootstrap.php';
129 12
		if (!is_file($bootstrapFile)) {
130 1
			$this->log("Info: bootstrap.php was not found in working directory.", 'dark_gray');
131 1
			return NULL;
132
		}
133 11
		$this->log("Info: Found bootstrap.php in working directory.", 'dark_gray');
134 11
		$container = require_once $bootstrapFile;
135 11
		if ($container === 1 || $container === TRUE) { // 1 = success, TRUE = already required
136 2
			return NULL;
137 11
		} elseif ($container instanceof Container) {
138 10
			return $container;
139
		}
140 1
		$this->log("Returned value from bootstrap.php must be instance of 'Genesis\\Container\\Container' or nothing (NULL).", 'red');
141 1
		$this->terminate(255);
142
	}
143
144
145
	/**
146
	 * @param $configFile
147
	 * @param Container|NULL $bootstrapContainer
148
	 * @return Container
149
	 */
150 11
	private function createContainer($configFile, Container $bootstrapContainer = NULL)
151
	{
152 11
		$factory = new ContainerFactory();
153 11
		$factory->addConfig($this->workingDir . '/' . $configFile);
154 11
		if (is_file($this->workingDir . '/config.local.neon')) {
155
			$factory->addConfig($this->workingDir . '/config.local.neon');
156
		}
157 11
		$factory->setWorkingDirectory($this->workingDir);
158 11
		if ($bootstrapContainer !== NULL) {
159 10
			$factory->addContainerToMerge($bootstrapContainer);
160 10
		}
161 11
		return $factory->create();
162
	}
163
164
165
	/**
166
	 * @param Container $container
167
	 * @return Build
168
	 */
169 11
	private function createBuild(Container $container, array $arguments)
170
	{
171 11
		if ($this->buildFactory === NULL) {
172
			throw new InvalidStateException("Build factory was not setted.");
173
		}
174 11
		return $this->buildFactory->create($container, $arguments);
175
	}
176
177
	/**
178
	 * @param Build $build
179
	 * @param $task
180
	 * @param array|NULL $arguments
181
	 */
182 9
	private function invokeTask(Build $build, $task, array $arguments)
183
	{
184 9
		$method = 'run' . str_replace('-', '', ucfirst($task));
185 9
		if (!method_exists($build, $method)) {
186 1
			$this->log("Task '$task' does not exists.", 'red');
187 1
			$this->terminate(255);
188
		}
189 8
		$this->log("Running [$task]", 'green');
190 8
		$args = array_slice($arguments, 1); // first argument is task name, slice it
191 8
		call_user_func_array([$build, $method], $args);
192 7
	}
193
194
195
	/**
196
	 * @param \Exception|\Throwable $e
197
	 * @throws TerminateException
198
	 */
199 3
	private function handleException($e)
200
	{
201 3
		$this->log("Exited with ERROR:", 'red');
202 3
		$this->log($e->getMessage(), 'red');
203 3
		echo $e->getTraceAsString() . PHP_EOL;
204 3
		$this->terminate(255);
205
	}
206
207
208
	/**
209
	 * @param string $message
210
	 * @param string|null $color
211
	 * @param string|null $backgroundColor
212
	 */
213 13
	private function log($message, $color = NULL, $backgroundColor = NULL)
214
	{
215 13
		echo Cli::getColoredString($message . PHP_EOL, $color, $backgroundColor);
216 13
	}
217
218
}