Completed
Push — master ( e64760...31785d )
by Richard
05:42
created

App::run()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2.0185

Importance

Changes 0
Metric Value
dl 0
loc 19
ccs 10
cts 12
cp 0.8333
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 11
nc 2
nop 1
crap 2.0185
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\App\RuleLoader;
14
use Lechimp\Dicto\Definition\RuleParser;
15
use Lechimp\Dicto\Rules\Ruleset;
16
use Lechimp\Dicto\Rules as R;
17
use Lechimp\Dicto\Variables as V;
18
use Symfony\Component\Yaml\Yaml;
19
use Pimple\Container;
20
use PhpParser\ParserFactory;
21
22
/**
23
 * The App to be run from a script.
24
 */
25
class App {
26 10
    public function __construct() {
27 10
        ini_set('xdebug.max_nesting_level', 200);
28 10
    }
29
30
    /**
31
     * Run the app.
32
     *
33
     * @param   array   $params     from commandline
34
     * @return  null
35
     */
36 2
    public function run(array $params) {
37 1
        if (count($params) < 2) {
38
            throw new \RuntimeException(
39
                "Expected path to config-file as first parameter.");
40
        }
41
42
        // drop program name
43 2
        array_shift($params);
44
45
        // the rest of the params are paths to configs
46 1
        list($config_file_path, $configs) = $this->load_configs($params);
47 1
        $t = explode("/", $config_file_path);
48 1
        array_pop($t);
49 1
        $config_file_path = implode("/", $t);
50
51 1
        $dic = $this->create_dic($config_file_path, $configs);
52
53 1
        $dic["engine"]->run();
54 1
    }
55
56
    /**
57
     * Load extra configs from yaml files.
58
     *
59
     * @param   array   $config_file_paths
60
     * @return  array
61
     */
62 6
    protected function load_configs(array $config_file_paths) {
63 6
        $configs_array = array();
64 6
        $config_file_path = null;
65 6
        foreach ($config_file_paths as $config_file) {
66 6
            if (!file_exists($config_file)) {
67
                throw new \RuntimeException("Unknown config-file '$config_file'");
68
            }
69 6
            if ($config_file_path === null) {
70 6
                $config_file_path = $config_file;
71 6
            }
72 6
            $configs_array[] = Yaml::parse(file_get_contents($config_file));
73 6
        }
74 6
        return array($config_file_path, $configs_array);
75
    }
76
77
    /**
78
     * Loads the schemas defined in the config.
79
     *
80
     * @param   array   $schema_classes
81
     * @return  R\Schema[]
82
     */
83 3
    protected function load_schemas(array $schema_classes) {
84 3
        $schemas = array();
85 3
        foreach ($schema_classes as $schema_class) {
86 3
            $schema = new $schema_class;
87 3
            if (!($schema instanceof R\Schema)) {
88
                throw new \RuntimeException("'$schema_class' is not a Schema-class.");
89
            }
90 3
            $schemas[] = $schema;
91 3
        }
92 3
        return $schemas;
93
    }
94
95
    /**
96
     * Loads the properties defined in the config.
97
     *
98
     * @param   array   $property_classes
99
     * @return  R\Schema[]
100
     */
101 3
    protected function load_properties(array $property_classes) {
102 3
        $properties = array();
103 3
        foreach ($property_classes as $property_class) {
104 3
            $property = new $property_class;
105 3
            if (!($property instanceof V\Property)) {
106
                throw new \RuntimeException("'$property_class' is not a Schema-class.");
107
            }
108 3
            $properties[] = $property;
109 3
        }
110 3
        return $properties;
111
    }
112
113
    /**
114
     * Loads the variables defined in the config.
115
     *
116
     * @param   array   $variable_classes
117
     * @return  R\Schema[]
118
     */
119 3
    protected function load_variables(array $variable_classes) {
120 3
        $variables = array();
121 3
        foreach ($variable_classes as $variable_class) {
122 3
            $variable = new $variable_class;
123 3
            if (!($variable instanceof V\Variable)) {
124
                throw new \RuntimeException("'$variable_class' is not a Schema-class.");
125
            }
126 3
            $variables[] = $variable;
127 3
        }
128 3
        return $variables;
129
    }
130
131
    /**
132
     * Create and initialize the DI-container.
133
     *
134
     * @param   string      $config_file_path
135
     * @param   array       &$configs
136
     * @return  Container
137
     */
138 6
    protected function create_dic($config_file_path, array &$configs) {
139 6
        array('is_string($rule_file_path)');
140
141 6
        $container = new Container();
142
143
        $container["config"] = function () use ($config_file_path, &$configs) {
144 5
            return new Config($config_file_path, $configs);
145
        };
146
147
        $container["ruleset"] = function($c) {
148 1
            $rule_file_path = $c["config"]->project_rules();
149 1
            if (!file_exists($rule_file_path)) {
150
                throw new \RuntimeException("Unknown rule-file '$rule_file_path'");
151
            }
152 1
            $ruleset = $c["rule_loader"]->load_rules_from($rule_file_path);
153 1
            return $ruleset;
154
        };
155
156
        $container["rule_loader"] = function($c) {
157 1
            return new RuleLoader($c["rule_parser"]);
158
        };
159
160
        $container["rule_parser"] = function($c) {
161
            return new RuleParser
162 1
                ( $c["variables"]
163 1
                , $c["schemas"]
164 1
                , $c["properties"]
165 1
                );
166
        };
167
168
        $container["engine"] = function($c) {
169
            return new Engine
170 1
                ( $c["log"]
171 1
                , $c["config"]
172 1
                , $c["database_factory"]
173 1
                , $c["indexer_factory"]
174 1
                , $c["analyzer_factory"]
175 1
                , $c["source_status"]
176 1
                );
177
        };
178
179
        $container["log"] = function () {
180 2
            return new CLILogger();
181
        };
182
183
        $container["database_factory"] = function() {
184 1
            return new DBFactory();
185
        };
186
187
        $container["indexer_factory"] = function($c) {
188
            return new \Lechimp\Dicto\Indexer\IndexerFactory
189 2
                ( $c["log"]
190 2
                , $c["php_parser"]
191 2
                , array
192 2
                    ( new \Lechimp\Dicto\Rules\ContainText()
193 2
                    , new \Lechimp\Dicto\Rules\DependOn()
194 2
                    , new \Lechimp\Dicto\Rules\Invoke()
195 2
                    )
196 2
                );
197
        };
198
199
        $container["analyzer_factory"] = function($c) {
200
            return new \Lechimp\Dicto\Analysis\AnalyzerFactory
201 1
                ( $c["log"]
202 1
                , $c["ruleset"]
203 1
                );
204
        };
205
206
        $container["php_parser"] = function() {
207 2
            return (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
208
        };
209
210
        $container["report_generator"] = function() {
211
            return new CLIReportGenerator();
212
        };
213
214
        $container["source_status"] = function($c) {
215 2
            return new SourceStatusGit($c["config"]->project_root());
216
        };
217
218
        $container["schemas"] = function($c) {
219 2
            return $this->load_schemas($c["config"]->rules_schemas());
220
        };
221
222
        $container["properties"] = function($c) {
223 2
            return $this->load_properties($c["config"]->rules_properties());
224
        };
225
226 2
        $container["variables"] = function($c) {
227 2
            return $this->load_variables($c["config"]->rules_variables());
228
        };
229
230 6
        return $container;
231
    }
232
}
233