Completed
Push — 57-formatter-per-extension ( 73b3c8 )
by Nicolas
40:17 queued 36:16
created

Parser::enableGroupSupport()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
rs 9.6667
cc 2
eloc 4
nc 2
nop 0
1
<?php
2
3
namespace Karma\Configuration;
4
5
use Gaufrette\Filesystem;
6
use Karma\Configuration\Parser\NullParser;
7
use Karma\Configuration\Parser\IncludeParser;
8
use Karma\Configuration\Parser\VariableParser;
9
use Karma\Configuration\Parser\ExternalParser;
10
use Psr\Log\NullLogger;
11
use Karma\Configuration\Parser\GroupParser;
12
13
class Parser
14
{
15
    use \Karma\Logging\LoggerAware;
16
    
17
    const
18
        INCLUDES = 'includes',
19
        VARIABLES = 'variables',
20
        EXTERNALS = 'externals',
21
        GROUPS = 'groups';
22
    
23
    private
24
        $parsers,
0 ignored issues
show
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
25
        $currentParser,
26
        $parsedFiles,
27
        $fs,
28
        $eol;
29
    
30
    public function __construct(Filesystem $fs)
31
    {
32
        $this->logger = new NullLogger();
33
        
34
        $this->parsers = array(
35
            self::VARIABLES => new VariableParser(),  
36
        );
37
38
        $this->parsedFiles = array();
39
        $this->fs = $fs; 
40
        $this->eol = "\n";
41
    }
42
    
43
    public function setEOL($eol)
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

This check looks for method names that are not written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection seeker becomes databaseConnectionSeeker.

Loading history...
44
    {
45
        $this->eol = $eol;
46
        
47
        return $this;
48
    }
49
    
50
    public function enableIncludeSupport()
51
    {
52
        if(! isset($this->parsers[self::INCLUDES]))
53
        {
54
            $this->parsers[self::INCLUDES] = new IncludeParser();
55
        }
56
        
57
        return $this;
58
    }
59
    
60
    public function enableExternalSupport()
61
    {
62
        if(! isset($this->parsers[self::EXTERNALS]))
63
        {
64
            $this->parsers[self::EXTERNALS] = new ExternalParser(new Parser($this->fs));
65
        }
66
        
67
        return $this;
68
    }
69
    
70
    public function enableGroupSupport()
71
    {
72
        if(! isset($this->parsers[self::GROUPS]))
73
        {
74
            $this->parsers[self::GROUPS] = new GroupParser();
75
        }
76
        
77
        return $this;
78
    }
79
    
80
    public function parse($masterFilePath)
81
    {
82
        try
83
        {
84
            $this->parseFromMasterFile($masterFilePath);
85
            
86
            $variables = $this->getVariables();
87
            $this->printExternalFilesStatus();
88
            
89
            $this->postParse();
90
            
91
            return $variables;
92
        }
93
        catch(\RuntimeException $e)
94
        {
95
            $this->error($e->getMessage());
96
            throw $e;
97
        }
98
    }
99
    
100
    private function parseFromMasterFile($masterFilePath)
101
    {
102
        $files = array($masterFilePath);
103
        
104
        while(! empty($files))
105
        {
106
            foreach($files as $file)
107
            {
108
                $this->readFile($file);
109
            }
110
            
111
            if(isset($this->parsers[self::INCLUDES]))
112
            {
113
                $includeParser = $this->parsers[self::INCLUDES];
114
                $files = $includeParser->getCollectedFiles();
0 ignored issues
show
Bug introduced by
The method getCollectedFiles does only exist in Karma\Configuration\Parser\IncludeParser, but not in Karma\Configuration\Pars...n\Parser\VariableParser.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
115
            }
116
117
            // Avoid loop
118
            $files = array_diff($files, $this->parsedFiles);
119
        }
120
    }
121
    
122
    private function readFile($filePath)
123
    {
124
        $lines = $this->extractLines($filePath);
125
        $this->changeCurrentFile($filePath);
126
        
127
        $this->currentParser = new NullParser();
128
        $currentLineNumber = 0;
129
        
130
        foreach($lines as $line)
131
        {
132
            $currentLineNumber++;
133
            
134
            $sectionName = $this->extractSectionName($line);
135
            if($sectionName !== null)
136
            {
137
                $this->switchSectionParser($sectionName);
138
                continue;
139
            }
140
141
            $this->currentParser->parse($line, $currentLineNumber);
142
        }
143
        
144
        $this->parsers[self::VARIABLES]->endOfFileCheck();
0 ignored issues
show
Bug introduced by
The method endOfFileCheck does only exist in Karma\Configuration\Parser\VariableParser, but not in Karma\Configuration\Pars...on\Parser\IncludeParser.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
145
    }
146
    
147
    private function extractLines($filePath)
148
    {
149
        if(! $this->fs->has($filePath))
150
        {
151
            throw new \RuntimeException("$filePath does not exist");
152
        }
153
        
154
        $content = $this->fs->read($filePath);
155
156
        $lines = explode($this->eol, $content);
157
        $lines = $this->trimLines($lines);
158
        $lines = $this->removeEmptyLines($lines);
159
160
        $this->parsedFiles[] = $filePath;
161
        
162
        if(empty($lines))
163
        {
164
            $this->warning("Empty file ($filePath)");
165
        }
166
        
167
        return $lines;
168
    }
169
    
170
    private function trimLines(array $lines)
171
    {
172
        return array_map('trim', $lines);
173
    }
174
    
175
    private function removeEmptyLines(array $lines)
176
    {
177
        return array_filter($lines);
178
    }
179
    
180
    private function changeCurrentFile($filePath)
181
    {
182
        $this->info("Reading $filePath");
183
        
184
        foreach($this->parsers as $parser)
185
        {
186
            $parser->setCurrentFile($filePath);
187
        }
188
    }
189
    
190
    private function extractSectionName($line)
191
    {
192
        $sectionName = null;
193
        
194
        // [.*]
195
        if(preg_match('~^\[(?P<groupName>[^\]]+)\]$~', $line, $matches))
196
        {
197
            $sectionName = trim(strtolower($matches['groupName']));
198
        }
199
        
200
        return $sectionName;
201
    }
202
    
203
    private function switchSectionParser($sectionName)
204
    {
205
        if(! isset($this->parsers[$sectionName]))
206
        {
207
            throw new \RuntimeException('Unknown section name ' . $sectionName);
208
        }
209
        
210
        $this->currentParser = $this->parsers[$sectionName];
211
    }
212
    
213
    private function getVariables()
214
    {
215
        return $this->parsers[self::VARIABLES]->getVariables();
0 ignored issues
show
Bug introduced by
The method getVariables does only exist in Karma\Configuration\Parser\VariableParser, but not in Karma\Configuration\Pars...on\Parser\IncludeParser.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
216
    }
217
    
218
    public function getFileSystem()
219
    {
220
        return $this->fs;
221
    }
222
    
223
    public function getExternalVariables()
224
    {
225
        $variables = array();
226
        
227
        if(isset($this->parsers[self::EXTERNALS]))
228
        {
229
            $variables = $this->parsers[self::EXTERNALS]->getExternalVariables();
0 ignored issues
show
Bug introduced by
The method getExternalVariables does only exist in Karma\Configuration\Parser\ExternalParser, but not in Karma\Configuration\Pars...n\Parser\VariableParser.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
230
        }
231
        
232
        return $variables;
233
    }
234
    
235
    private function printExternalFilesStatus()
236
    {
237
        $files = $this->getExternalFilesStatus();
238
        
239
        foreach($files as $file => $status)
240
        {
241
            $message = sprintf(
242
               'External file %s was %s',
243
               $file,
244
               $status['found'] ? 'found' : '<options=bold>not found</options=bold>'
245
            );
246
            
247
            $this->warning($message);
248
        }
249
    }
250
    
251
    private function getExternalFilesStatus()
252
    {
253
        $files = array();
254
        
255
        if(isset($this->parsers[self::EXTERNALS]))
256
        {
257
            $files = $this->parsers[self::EXTERNALS]->getExternalFilesStatus();
0 ignored issues
show
Bug introduced by
The method getExternalFilesStatus does only exist in Karma\Configuration\Parser\ExternalParser, but not in Karma\Configuration\Pars...n\Parser\VariableParser.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
258
        }
259
        
260
        return $files;
261
    }
262
    
263
    public function getGroups()
264
    {
265
        $groups = array();
266
        
267
        if(isset($this->parsers[self::GROUPS]))
268
        {
269
            $groups = $this->parsers[self::GROUPS]->getCollectedGroups();
0 ignored issues
show
Bug introduced by
The method getCollectedGroups does only exist in Karma\Configuration\Parser\GroupParser, but not in Karma\Configuration\Pars...n\Parser\VariableParser.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
270
        }
271
        
272
        return $groups;
273
    }
274
    
275
    private function postParse()
276
    {
277
        foreach($this->parsers as $parser)
278
        {
279
            $parser->postParse();
280
        }
281
    }
282
}