These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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 | * Bootstrap |
||
14 | */ |
||
15 | class Bootstrap |
||
16 | { |
||
17 | |||
18 | const DEFAULT_CONFIG_FILE = 'config.neon'; |
||
19 | |||
20 | |||
21 | public function run(InputArgs $inputArgs) |
||
22 | { |
||
23 | $workingDir = getcwd(); |
||
24 | if ($inputArgs->getOption('colors') !== NULL && !$inputArgs->getOption('colors')) { |
||
25 | Cli::$enableColors = FALSE; |
||
26 | } |
||
27 | if ($inputArgs->getOption('working-dir')) { |
||
28 | $workingDir = realpath($inputArgs->getOption('working-dir')); |
||
29 | if (!$workingDir) { |
||
30 | $this->log(sprintf("Working dir '%s' does not exists.", $inputArgs->getOption('working-dir')), 'red'); |
||
31 | exit(255); |
||
32 | } |
||
33 | } |
||
34 | if ($workingDir === __DIR__) { |
||
35 | $this->log(sprintf("Working dir '%s' is directory with Genesis. You have to choose directory with build.", $workingDir), 'red'); |
||
36 | exit(255); |
||
37 | } |
||
38 | |||
39 | $arguments = $inputArgs->getArguments(); |
||
40 | if(isset($arguments[0]) && $arguments[0] === 'self-init'){ |
||
41 | $directoryName = isset($arguments[1]) ? $arguments[1] : 'build'; |
||
42 | $selfInit = new Commands\SelfInit(); |
||
43 | $selfInit->setDistDirectory(__DIR__ . '/build-dist'); |
||
44 | $selfInit->setWorkingDirectory($workingDir); |
||
45 | $selfInit->setDirname($directoryName); |
||
46 | $selfInit->execute(); |
||
47 | exit(0); |
||
48 | } |
||
49 | |||
50 | $bootstrapFile = $this->detectBootstrapFilename($workingDir); |
||
51 | $container = NULL; |
||
52 | if (is_file($bootstrapFile)) { |
||
53 | $this->log("Info: Found bootstrap.php in working directory.", 'dark_gray'); |
||
54 | $container = require_once $bootstrapFile; |
||
55 | if($container === 1 || $container === TRUE){ // 1 = success, TRUE = already required |
||
56 | $container = NULL; |
||
57 | }elseif(!($container instanceof Container)){ |
||
58 | $this->log("Returned value from bootstrap.php must be instance of 'Genesis\\Container\\Container' or nothing (NULL).", 'red'); |
||
59 | exit(255); |
||
60 | } |
||
61 | } else { |
||
62 | $this->log("Info: bootstrap.php was not found in working directory.", 'dark_gray'); |
||
63 | } |
||
64 | |||
65 | $arguments = $inputArgs->getArguments(); |
||
66 | $configFile = $inputArgs->getOption('config') ? $inputArgs->getOption('config') : self::DEFAULT_CONFIG_FILE; |
||
67 | try { |
||
68 | $container = $this->createContainer($workingDir, $configFile, $container); |
||
69 | $build = $this->createBuild($container, $arguments); |
||
70 | } catch (\Exception $e) { |
||
71 | $this->log("Exited with ERROR:", 'red'); |
||
72 | $this->log($e->getMessage(), 'red'); |
||
73 | echo $e->getTraceAsString() . PHP_EOL; |
||
74 | exit(255); |
||
75 | } |
||
76 | if (count($arguments) < 1) { |
||
77 | $this->log("Running default", 'green'); |
||
78 | $build->runDefault(); |
||
79 | exit(0); |
||
80 | } |
||
81 | |||
82 | $method = 'run' . str_replace('-', '', ucfirst($arguments[0])); |
||
83 | if (!method_exists($build, $method)) { |
||
84 | $this->log("Task '$arguments[0]' does not exists.", 'red'); |
||
85 | exit(255); |
||
86 | } |
||
87 | $this->log("Running [$arguments[0]]", 'green'); |
||
88 | try { |
||
89 | $build->$method(); |
||
90 | } catch (\Exception $e) { |
||
91 | $this->log("Exited with ERROR:", 'red'); |
||
92 | $this->log($e->getMessage(), 'red'); |
||
93 | echo $e->getTraceAsString() . PHP_EOL; |
||
94 | exit(255); |
||
95 | } |
||
96 | $this->log("Exited with SUCCESS", 'black', 'green'); |
||
97 | echo PHP_EOL; |
||
98 | exit(0); |
||
99 | } |
||
100 | |||
101 | |||
102 | protected function detectBootstrapFilename($workingDir) |
||
103 | { |
||
104 | return $workingDir . DIRECTORY_SEPARATOR . 'bootstrap.php'; |
||
105 | } |
||
106 | |||
107 | |||
108 | /** |
||
109 | * @return Container |
||
110 | */ |
||
111 | protected function createContainer($workingDir, $configFile, Container $bootstrapContainer = NULL) |
||
112 | { |
||
113 | $factory = new ContainerFactory(); |
||
114 | $factory->addConfig($workingDir . '/' . $configFile); |
||
115 | if(is_file($workingDir . '/config.local.neon')){ |
||
116 | $factory->addConfig($workingDir . '/config.local.neon'); |
||
117 | } |
||
118 | $factory->setWorkingDirectory($workingDir); |
||
119 | if($bootstrapContainer !== NULL){ |
||
120 | $factory->addContainerToMerge($bootstrapContainer); |
||
121 | } |
||
122 | return $factory->create(); |
||
123 | } |
||
124 | |||
125 | |||
126 | /** |
||
127 | * @param Container $container |
||
128 | * @return Build |
||
129 | */ |
||
130 | protected function createBuild(Container $container, array $arguments = NULL) |
||
131 | { |
||
132 | $class = $container->getClass(); |
||
133 | if (!class_exists($class, TRUE)) { |
||
134 | $this->log(sprintf( |
||
135 | "Build class '%s' was not found." . PHP_EOL . |
||
136 | "Are you in correct working directory?" . PHP_EOL . |
||
137 | "Did you forget add bootstrap.php with class loading into working directory?" . PHP_EOL . |
||
138 | "Did you forget to load class %s?", $class, $class), 'red'); |
||
139 | exit(255); |
||
1 ignored issue
–
show
|
|||
140 | } |
||
141 | $build = new $class($container, $arguments); |
||
142 | if (!($build instanceof IBuild)) { |
||
143 | throw new \RuntimeException("Instance of build does not implements interface IBuild."); |
||
144 | } |
||
145 | $this->autowire($build, $container); |
||
146 | $build->setup(); |
||
147 | return $build; |
||
148 | } |
||
149 | |||
150 | |||
151 | protected function autowire(IBuild $build, Container $container) |
||
152 | { |
||
153 | foreach ($this->getAutowiredProperties($build) as $property => $service) { |
||
154 | if(!$container->hasService($service)){ |
||
155 | throw new \RuntimeException("Cannot found service '$service' to inject into " . get_class($build) . "::$property."); |
||
156 | } |
||
157 | $build->$property = $container->getService($service); |
||
158 | } |
||
159 | } |
||
160 | |||
161 | |||
162 | protected function getAutowiredProperties($class) |
||
163 | { |
||
164 | $return = []; |
||
165 | $reflectionClass = new \ReflectionClass($class); |
||
166 | foreach($reflectionClass->getProperties(\ReflectionProperty::IS_PUBLIC) as $property){ |
||
167 | $reflectionProp = new \ReflectionProperty($class, $property->getName()); |
||
168 | $doc = $reflectionProp->getDocComment(); |
||
169 | if(preg_match('#@inject ?([^\s]*)\s#s', $doc, $matches)){ |
||
170 | $return[$property->getName()] = trim($matches[1]) !== '' ? $matches[1] : $property->getName(); |
||
171 | } |
||
172 | } |
||
173 | return $return; |
||
174 | } |
||
175 | |||
176 | |||
177 | protected function log($message, $color = NULL, $backgroundColor = NULL) |
||
178 | { |
||
179 | echo Cli::getColoredString($message . PHP_EOL, $color, $backgroundColor); |
||
180 | } |
||
181 | |||
182 | } |
An exit expression should only be used in rare cases. For example, if you write a short command line script.
In most cases however, using an
exit
expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.