Completed
Push — master ( 1e9ef5...3740bc )
by Richard
05:53 queued 29s
created

App::build_report_generator()   C

Complexity

Conditions 7
Paths 16

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 7

Importance

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