Completed
Push — master ( 9b2a73...93cace )
by Richard
05:06
created

App::configure_runtime()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 10
cts 10
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 9
nc 2
nop 1
crap 2
1
<?php
2
/******************************************************************************
3
 * An implementation of dicto (scg.unibe.ch/dicto) in and for PHP.
4
 * 
5
 * Copyright (c) 2016 Richard Klees <[email protected]>
6
 *
7
 * This software is licensed under The MIT License. You should have received 
8
 * a copy of the license along with the code.
9
 */
10
11
namespace Lechimp\Dicto\App;
12
13
use Lechimp\Dicto\Analysis\CombinedReportGenerators;
14
use Lechimp\Dicto\Analysis\ReportGenerator;
15
use Lechimp\Dicto\App\RuleLoader;
16
use Lechimp\Dicto\Definition\RuleParser;
17
use Lechimp\Dicto\Rules\Ruleset;
18
use Lechimp\Dicto\Rules as R;
19
use Lechimp\Dicto\Variables as V;
20
use Symfony\Component\Yaml\Yaml;
21
use Pimple\Container;
22
use PhpParser\ParserFactory;
23
24
/**
25
 * The App to be run from a script.
26
 */
27
class App {
28 16
    public function __construct() {
29 16
        ini_set('xdebug.max_nesting_level', 200);
30 16
    }
31
32
    /**
33
     * Run the app.
34
     *
35
     * @param   array   $params     from commandline
36
     * @return  null
37
     */
38 1
    public function run(array $params) {
39 1
        if (count($params) < 2) {
40
            throw new \RuntimeException(
41
                "Expected path to config-file as first parameter.");
42
        }
43
44
        // drop program name
45 1
        array_shift($params);
46
47
        // the rest of the params are paths to configs
48 1
        list($config_file_path, $configs) = $this->load_configs($params);
49 1
        $t = explode("/", $config_file_path);
50 1
        array_pop($t);
51 1
        $config_file_path = implode("/", $t);
52
53 1
        $dic = $this->create_dic($config_file_path, $configs);
54
55 1
        $this->configure_runtime($dic["config"]);
56
57 1
        $dic["engine"]->run();
58 1
    }
59
60
    /**
61
     * Create and initialize the DI-container.
62
     *
63
     * @param   string      $config_file_path
64
     * @param   array       &$configs
65
     * @return  Container
66
     */
67 10
    protected function create_dic($config_file_path, array &$configs) {
68 10
        array('is_string($rule_file_path)');
69
70 10
        $container = new Container();
71
72
        $container["config"] = function () use ($config_file_path, &$configs) {
73 9
            return new Config($config_file_path, $configs);
74
        };
75
76
        $container["ruleset"] = function($c) {
77 1
            $rule_file_path = $c["config"]->project_rules();
78 1
            if (!file_exists($rule_file_path)) {
79 1
                throw new \RuntimeException("Unknown rule-file '$rule_file_path'");
80
            }
81 1
            $ruleset = $c["rule_loader"]->load_rules_from($rule_file_path);
82 1
            return $ruleset;
83
        };
84
85
        $container["rule_loader"] = function($c) {
86 1
            return new RuleLoader($c["rule_parser"]);
87
        };
88
89
        $container["rule_parser"] = function($c) {
90
            return new RuleParser
91 1
                ( $c["variables"]
92 1
                , $c["schemas"]
93 1
                , $c["properties"]
94 1
                );
95
        };
96
97
        $container["engine"] = function($c) {
98
            return new Engine
99 1
                ( $c["log"]
100 1
                , $c["config"]
101 1
                , $c["database_factory"]
102 5
                , $c["indexer_factory"]
103 1
                , $c["analyzer_factory"]
104 1
                , $c["report_generator"]
105 1
                , $c["source_status"]
106 1
                );
107
        };
108
109
        $container["log"] = function () {
110 2
            return new CLILogger();
111
        };
112
113
        $container["database_factory"] = function() {
114 3
            return new DBFactory();
115
        };
116
117
        $container["indexer_factory"] = function($c) {
118
            return new \Lechimp\Dicto\Indexer\IndexerFactory
119 2
                ( $c["log"]
120 2
                , $c["php_parser"]
121 2
                , array
122 2
                    ( new \Lechimp\Dicto\Rules\ContainText()
123 2
                    , new \Lechimp\Dicto\Rules\DependOn()
124 2
                    , new \Lechimp\Dicto\Rules\Invoke()
125 2
                    )
126 2
                );
127
        };
128
129
        $container["analyzer_factory"] = function($c) {
130
            return new \Lechimp\Dicto\Analysis\AnalyzerFactory
131 1
                ( $c["log"]
132 1
                , $c["ruleset"]
133 1
                );
134
        };
135
136
        $container["php_parser"] = function() {
137
            $lexer = new \PhpParser\Lexer\Emulative
138 2
                (["usedAttributes" => ["comments", "startLine", "endLine", "startFilePos"]]);
139 2
            return (new ParserFactory)->create(ParserFactory::PREFER_PHP7, $lexer);
140
        };
141
142
        $container["report_generator"] = function($c) {
143 5
            return $this->build_report_generator($c);
144
        };
145
146
        $container["stdout_report_generator"] = function() {
147 3
            return new CLIReportGenerator();
148
        };
149
150
        $container["database_report_generator"] = function($c) {
151 2
            $path = $this->result_database_path($c["config"]);
152 2
            return $c["database_factory"]->get_result_db($path);
153
        };
154
155
        $container["source_status"] = function($c) {
156 2
            return new SourceStatusGit($c["config"]->project_root());
157
        };
158
159
        $container["schemas"] = function($c) {
160 2
            return $this->load_schemas($c["config"]->rules_schemas());
161
        };
162
163
        $container["properties"] = function($c) {
164 2
            return $this->load_properties($c["config"]->rules_properties());
165
        };
166
167 2
        $container["variables"] = function($c) {
168 2
            return $this->load_variables($c["config"]->rules_variables());
169
        };
170
171 10
        return $container;
172
    }
173
174
    /**
175
     * Configure php runtime.
176
     *
177
     * @param   Config  $config
178
     * @return  null
179
     */
180 2
    protected function configure_runtime(Config $config) {
181 2
        if ($config->runtime_check_assertions()) {
182 1
            assert_options(ASSERT_ACTIVE, true);
183 1
            assert_options(ASSERT_WARNING, true);
184 1
            assert_options(ASSERT_BAIL, false);
185 1
        }
186
        else {
187 1
            assert_options(ASSERT_ACTIVE, false);
188 1
            assert_options(ASSERT_WARNING, false);
189 1
            assert_options(ASSERT_BAIL, false);
190
        }
191 2
    }
192
193
    /**
194
     * Load extra configs from yaml files.
195
     *
196
     * @param   array   $config_file_paths
197
     * @return  array
198
     */
199 10
    protected function load_configs(array $config_file_paths) {
200 10
        $configs_array = array();
201 10
        $config_file_path = null;
202 10
        foreach ($config_file_paths as $config_file) {
203 10
            if (!file_exists($config_file)) {
204
                throw new \RuntimeException("Unknown config-file '$config_file'");
205
            }
206 10
            if ($config_file_path === null) {
207 10
                $config_file_path = $config_file;
208 10
            }
209 10
            $configs_array[] = Yaml::parse(file_get_contents($config_file));
210 10
        }
211 10
        return array($config_file_path, $configs_array);
212
    }
213
214
    /**
215
     * Loads the schemas defined in the config.
216
     *
217
     * @param   array   $schema_classes
218
     * @return  R\Schema[]
219
     */
220 3
    protected function load_schemas(array $schema_classes) {
221 3
        $schemas = array();
222 3
        foreach ($schema_classes as $schema_class) {
223 3
            $schema = new $schema_class;
224 3
            if (!($schema instanceof R\Schema)) {
225
                throw new \RuntimeException("'$schema_class' is not a Schema-class.");
226
            }
227 3
            $schemas[] = $schema;
228 3
        }
229 3
        return $schemas;
230
    }
231
232
    /**
233
     * Loads the properties defined in the config.
234
     *
235
     * @param   array   $property_classes
236
     * @return  R\Schema[]
237
     */
238 3
    protected function load_properties(array $property_classes) {
239 3
        $properties = array();
240 3
        foreach ($property_classes as $property_class) {
241 3
            $property = new $property_class;
242 3
            if (!($property instanceof V\Property)) {
243
                throw new \RuntimeException("'$property_class' is not a Schema-class.");
244
            }
245 3
            $properties[] = $property;
246 3
        }
247 3
        return $properties;
248
    }
249
250
    /**
251
     * Loads the variables defined in the config.
252
     *
253
     * @param   array   $variable_classes
254
     * @return  R\Schema[]
255
     */
256 3
    protected function load_variables(array $variable_classes) {
257 3
        $variables = array();
258 3
        foreach ($variable_classes as $variable_class) {
259 3
            $variable = new $variable_class;
260 3
            if (!($variable instanceof V\Variable)) {
261
                throw new \RuntimeException("'$variable_class' is not a Schema-class.");
262
            }
263 3
            $variables[] = $variable;
264 3
        }
265 3
        return $variables;
266
    }
267
268
    /**
269
     * Build the report generators.
270
     *
271
     * @param   Container       $c
272
     * @return  ReportGenerator
273
     */
274 5
    public function build_report_generator(Container $c) {
275 5
        $config = $c["config"];
276 5
        $stdout = $config->analysis_report_stdout();
277 5
        $db = $config->analysis_report_database();
278 5
        if ($stdout && $db) {
279
            return new CombinedReportGenerators
280 1
                ([$c["stdout_report_generator"]
281 1
                , $c["database_report_generator"]
282 1
                ]);
283
        }
284 4
        elseif($stdout) {
285 2
            return $c["stdout_report_generator"];
286
        }
287 2
        elseif($db) {
288 1
            return $c["database_report_generator"];
289
        }
290
291
        throw new \RuntimeException
292 1
            ("No need to run analysis if no report generator is defined.");
293
    }
294
295 2
    protected function result_database_path(Config $c) {
296 2
        return $c->project_storage()."/results.sqlite";
297
    }
298
}
299