Completed
Push — master ( 4fd125...05840b )
by Richard
05:36
created

App::build_report_generator()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 20
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 13
cts 13
cp 1
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 14
nc 4
nop 1
crap 5
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 2
            return (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
138
        };
139
140
        $container["report_generator"] = function($c) {
141 5
            return $this->build_report_generator($c);
142
        };
143
144
        $container["stdout_report_generator"] = function() {
145 3
            return new CLIReportGenerator();
146
        };
147
148
        $container["database_report_generator"] = function($c) {
149 2
            $path = $this->result_database_path($c["config"]);
150 2
            return $c["database_factory"]->get_result_db($path);
151
        };
152
153
        $container["source_status"] = function($c) {
154 2
            return new SourceStatusGit($c["config"]->project_root());
155
        };
156
157
        $container["schemas"] = function($c) {
158 2
            return $this->load_schemas($c["config"]->rules_schemas());
159
        };
160
161
        $container["properties"] = function($c) {
162 2
            return $this->load_properties($c["config"]->rules_properties());
163
        };
164
165 2
        $container["variables"] = function($c) {
166 2
            return $this->load_variables($c["config"]->rules_variables());
167
        };
168
169 10
        return $container;
170
    }
171
172
    /**
173
     * Configure php runtime.
174
     *
175
     * @param   Config  $config
176
     * @return  null
177
     */
178 2
    protected function configure_runtime(Config $config) {
179 2
        if ($config->runtime_check_assertions()) {
180 1
            assert_options(ASSERT_ACTIVE, true);
181 1
            assert_options(ASSERT_WARNING, true);
182 1
            assert_options(ASSERT_BAIL, false);
183 1
        }
184
        else {
185 1
            assert_options(ASSERT_ACTIVE, false);
186 1
            assert_options(ASSERT_WARNING, false);
187 1
            assert_options(ASSERT_BAIL, false);
188
        }
189 2
    }
190
191
    /**
192
     * Load extra configs from yaml files.
193
     *
194
     * @param   array   $config_file_paths
195
     * @return  array
196
     */
197 10
    protected function load_configs(array $config_file_paths) {
198 10
        $configs_array = array();
199 10
        $config_file_path = null;
200 10
        foreach ($config_file_paths as $config_file) {
201 10
            if (!file_exists($config_file)) {
202
                throw new \RuntimeException("Unknown config-file '$config_file'");
203
            }
204 10
            if ($config_file_path === null) {
205 10
                $config_file_path = $config_file;
206 10
            }
207 10
            $configs_array[] = Yaml::parse(file_get_contents($config_file));
208 10
        }
209 10
        return array($config_file_path, $configs_array);
210
    }
211
212
    /**
213
     * Loads the schemas defined in the config.
214
     *
215
     * @param   array   $schema_classes
216
     * @return  R\Schema[]
217
     */
218 3
    protected function load_schemas(array $schema_classes) {
219 3
        $schemas = array();
220 3
        foreach ($schema_classes as $schema_class) {
221 3
            $schema = new $schema_class;
222 3
            if (!($schema instanceof R\Schema)) {
223
                throw new \RuntimeException("'$schema_class' is not a Schema-class.");
224
            }
225 3
            $schemas[] = $schema;
226 3
        }
227 3
        return $schemas;
228
    }
229
230
    /**
231
     * Loads the properties defined in the config.
232
     *
233
     * @param   array   $property_classes
234
     * @return  R\Schema[]
235
     */
236 3
    protected function load_properties(array $property_classes) {
237 3
        $properties = array();
238 3
        foreach ($property_classes as $property_class) {
239 3
            $property = new $property_class;
240 3
            if (!($property instanceof V\Property)) {
241
                throw new \RuntimeException("'$property_class' is not a Schema-class.");
242
            }
243 3
            $properties[] = $property;
244 3
        }
245 3
        return $properties;
246
    }
247
248
    /**
249
     * Loads the variables defined in the config.
250
     *
251
     * @param   array   $variable_classes
252
     * @return  R\Schema[]
253
     */
254 3
    protected function load_variables(array $variable_classes) {
255 3
        $variables = array();
256 3
        foreach ($variable_classes as $variable_class) {
257 3
            $variable = new $variable_class;
258 3
            if (!($variable instanceof V\Variable)) {
259
                throw new \RuntimeException("'$variable_class' is not a Schema-class.");
260
            }
261 3
            $variables[] = $variable;
262 3
        }
263 3
        return $variables;
264
    }
265
266
    /**
267
     * Build the report generators.
268
     *
269
     * @param   Container       $c
270
     * @return  ReportGenerator
271
     */
272 5
    public function build_report_generator(Container $c) {
273 5
        $config = $c["config"];
274 5
        $stdout = $config->analysis_report_stdout();
275 5
        $db = $config->analysis_report_database();
276 5
        if ($stdout && $db) {
277
            return new CombinedReportGenerators
278 1
                ([$c["stdout_report_generator"]
279 1
                , $c["database_report_generator"]
280 1
                ]);
281
        }
282 4
        elseif($stdout) {
283 2
            return $c["stdout_report_generator"];
284
        }
285 2
        elseif($db) {
286 1
            return $c["database_report_generator"];
287
        }
288
289
        throw new \RuntimeException
290 1
            ("No need to run analysis if no report generator is defined.");
291
    }
292
293 2
    protected function result_database_path(Config $c) {
294 2
        return $c->project_storage()."/results.sqlite";
295
    }
296
}
297