Completed
Push — master ( 86b2cd...b16d12 )
by Richard
03:26
created

DIC   C

Complexity

Total Complexity 17

Size/Duplication

Total Lines 196
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 19

Importance

Changes 0
Metric Value
dl 0
loc 196
rs 6.875
c 0
b 0
f 0
wmc 17
lcom 0
cbo 19

6 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 108 2
A load_schemas() 0 11 3
A load_properties() 0 11 3
A load_variables() 0 11 3
B build_analysis_listener() 0 20 5
A result_database_path() 0 3 1
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\CombinedListener;
14
use Lechimp\Dicto\Analysis\Listener;
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 Lechimp\Dicto\Report;
21
use Pimple\Container;
22
use PhpParser\ParserFactory;
23
24
/**
25
 * The dependency injection container for the app.
26
 */
27
class DIC extends Container {
28
    public function __construct(Config $config) {
29
        $this["config"] = $config;
30
31
        $this["ruleset"] = function($c) {
32
            $rule_file_path = $c["config"]->project_rules();
33
            if (!file_exists($rule_file_path)) {
34
                throw new \RuntimeException("Unknown rule-file '$rule_file_path'");
35
            }
36
            $ruleset = $c["rule_loader"]->load_rules_from($rule_file_path);
37
            return $ruleset;
38
        };
39
40
        $this["rule_loader"] = function($c) {
41
            return new RuleLoader($c["rule_parser"]);
42
        };
43
44
        $this["rule_parser"] = function($c) {
45
            return new RuleParser
46
                ( $c["variables"]
47
                , $c["schemas"]
48
                , $c["properties"]
49
                );
50
        };
51
52
        $this["engine"] = function($c) {
53
            return new Engine
54
                ( $c["log"]
55
                , $c["config"]
56
                , $c["database_factory"]
57
                , $c["indexer_factory"]
58
                , $c["analyzer_factory"]
59
                , $c["analysis_listener"]
60
                , $c["source_status"]
61
                );
62
        };
63
64
        $this["log"] = function () {
65
            return new CLILogger();
66
        };
67
68
        $this["database_factory"] = function() {
69
            return new DBFactory();
70
        };
71
72
        $this["indexer_factory"] = function($c) {
73
            return new \Lechimp\Dicto\Indexer\IndexerFactory
74
                ( $c["log"]
75
                , $c["php_parser"]
76
                , array
77
                    ( new \Lechimp\Dicto\Rules\ContainText()
78
                    , new \Lechimp\Dicto\Rules\DependOn()
79
                    , new \Lechimp\Dicto\Rules\Invoke()
80
                    )
81
                );
82
        };
83
84
        $this["analyzer_factory"] = function($c) {
85
            return new \Lechimp\Dicto\Analysis\AnalyzerFactory
86
                ( $c["log"]
87
                , $c["ruleset"]
88
                );
89
        };
90
91
        $this["php_parser"] = function() {
92
            $lexer = new \PhpParser\Lexer\Emulative
93
                (["usedAttributes" => ["comments", "startLine", "endLine", "startFilePos"]]);
94
            return (new ParserFactory)->create(ParserFactory::PREFER_PHP7, $lexer);
95
        };
96
97
        $this["analysis_listener"] = function($c) {
98
            return $this->build_analysis_listener($c);
99
        };
100
101
        $this["stdout_analysis_listener"] = function() {
102
            return new CLIReportGenerator();
103
        };
104
105
        $this["result_database"] = function($c) {
106
            $path = $this->result_database_path($c["config"]);
107
            return $c["database_factory"]->get_result_db($path);
108
        };
109
110
        $this["report_generator"] = function($c) {
111
            return new Report\Generator($c["report_queries"]);
112
        };
113
114
        $this["report_queries"] = function($c) {
115
            return new Report\Queries($c["result_database"]);
116
        };
117
118
        $this["source_status"] = function($c) {
119
            return new SourceStatusGit($c["config"]->project_root());
120
        };
121
122
        $this["schemas"] = function($c) {
123
            return $this->load_schemas($c["config"]->rules_schemas());
124
        };
125
126
        $this["properties"] = function($c) {
127
            return $this->load_properties($c["config"]->rules_properties());
128
        };
129
130
        $this["variables"] = function($c) {
131
            return $this->load_variables($c["config"]->rules_variables());
132
        };
133
134
        return $this;
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
135
    }
136
137
    /**
138
     * Loads the schemas defined in the config.
139
     *
140
     * @param   array   $schema_classes
141
     * @return  R\Schema[]
142
     */
143
    protected function load_schemas(array $schema_classes) {
144
        $schemas = array();
145
        foreach ($schema_classes as $schema_class) {
146
            $schema = new $schema_class;
147
            if (!($schema instanceof R\Schema)) {
148
                throw new \RuntimeException("'$schema_class' is not a Schema-class.");
149
            }
150
            $schemas[] = $schema;
151
        }
152
        return $schemas;
153
    }
154
155
    /**
156
     * Loads the properties defined in the config.
157
     *
158
     * @param   array   $property_classes
159
     * @return  R\Schema[]
160
     */
161
    protected function load_properties(array $property_classes) {
162
        $properties = array();
163
        foreach ($property_classes as $property_class) {
164
            $property = new $property_class;
165
            if (!($property instanceof V\Property)) {
166
                throw new \RuntimeException("'$property_class' is not a Schema-class.");
167
            }
168
            $properties[] = $property;
169
        }
170
        return $properties;
171
    }
172
173
    /**
174
     * Loads the variables defined in the config.
175
     *
176
     * @param   array   $variable_classes
177
     * @return  R\Schema[]
178
     */
179
    protected function load_variables(array $variable_classes) {
180
        $variables = array();
181
        foreach ($variable_classes as $variable_class) {
182
            $variable = new $variable_class;
183
            if (!($variable instanceof V\Variable)) {
184
                throw new \RuntimeException("'$variable_class' is not a Schema-class.");
185
            }
186
            $variables[] = $variable;
187
        }
188
        return $variables;
189
    }
190
191
    /**
192
     * Build the listeners for analysis.
193
     *
194
     * @param   Container       $c
195
     * @return  Listener
196
     */
197
    public function build_analysis_listener(Container $c) {
198
        $config = $c["config"];
199
        $stdout = $config->analysis_report_stdout();
200
        $db = $config->analysis_report_database();
201
        if ($stdout && $db) {
202
            return new CombinedListener
203
                ([$c["stdout_analysis_listener"]
204
                , $c["result_database"]
205
                ]);
206
        }
207
        elseif($stdout) {
208
            return $c["stdout_analysis_listener"];
209
        }
210
        elseif($db) {
211
            return $c["result_database"];
212
        }
213
214
        throw new \RuntimeException
215
            ("No need to run analysis if no listener is defined.");
216
    }
217
218
    // TODO: This should totally go to config.
219
    protected function result_database_path(Config $c) {
220
        return $c->project_storage()."/results.sqlite";
221
    }
222
}
223