FileLoader   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 67.44%

Importance

Changes 0
Metric Value
dl 0
loc 121
ccs 29
cts 43
cp 0.6744
rs 10
c 0
b 0
f 0
wmc 13
lcom 1
cbo 3

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getData() 0 6 1
A getExtension() 0 8 2
A setExtension() 0 4 1
A initExtension() 0 13 2
A getFileParser() 0 8 2
A initFileParser() 0 6 1
A resolvePath() 0 25 4
1
<?php
2
3
namespace Nip\Config\Loaders;
4
5
use Nip\Config\Exception\RuntimeException;
6
use Nip\Config\FileParser\AbstractFileParser;
7
8
/**
9
 * Class FileLoader
10
 * @package Nip\Config\Loaders
11
 */
12
class FileLoader extends AbstractLoader
13
{
14
15
    /**
16
     * Registered config file extensions.
17
     * key is extension, value is reader instance or plugin name
18
     *
19
     * @var array
20
     */
21
    protected static $extensions = [
22
        'ini' => 'Ini',
23
        'php' => 'Php',
24
        'json' => 'Json',
25
        'xml' => 'Xml',
26
        'yaml' => 'Yaml',
27
    ];
28
    /**
29
     * @var
30
     */
31
    protected $extension = null;
32
    /**
33
     * @var AbstractFileParser[]
34
     */
35
    protected $fileParsers = [];
36
37
    /**
38
     * @return mixed
39
     */
40 1
    protected function getData()
41
    {
42 1
        $type = self::$extensions[$this->getExtension()];
43
44 1
        return $this->getFileParser($type)->setPath($this->getResolvedPath())->parse();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->getFilePar...solvedPath())->parse(); (array) is incompatible with the return type declared by the abstract method Nip\Config\Loaders\AbstractLoader::getData of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
45
    }
46
47
    /**
48
     * @return mixed
49
     */
50 1
    public function getExtension()
51
    {
52 1
        if ($this->extension === null) {
53 1
            $this->initExtension();
54
        }
55
56 1
        return $this->extension;
57
    }
58
59
    /**
60
     * @param string $extension
61
     */
62 1
    public function setExtension($extension)
63
    {
64 1
        $this->extension = $extension;
65 1
    }
66
67 1
    public function initExtension()
68
    {
69 1
        $filename = $this->getResolvedPath();
70 1
        $pathInfo = pathinfo($filename);
71 1
        if (!isset($pathInfo['extension'])) {
72
            throw new RuntimeException(sprintf(
73
                'Filename "%s" is missing an extension and cannot be auto-detected',
74
                $filename
75
            ));
76
        }
77
78 1
        $this->setExtension(strtolower($pathInfo['extension']));
79 1
    }
80
81
    /**
82
     * @param $type
83
     * @return AbstractFileParser
84
     */
85 1
    protected function getFileParser($type)
86
    {
87 1
        if (!isset($this->fileParsers[$type])) {
88 1
            $this->initFileParser($type);
89
        }
90
91 1
        return $this->fileParsers[$type];
92
    }
93
94
    /**
95
     * @param $type
96
     */
97 1
    protected function initFileParser($type)
98
    {
99 1
        $class = 'Nip\Config\FileParser\\' . $type;
100 1
        $parser = new $class();
101 1
        $this->fileParsers[$type] = $parser;
102 1
    }
103
104
    /**
105
     * @throws RuntimeException
106
     */
107 1
    protected function resolvePath()
108
    {
109 1
        $filename = $this->getPath();
110 1
        if (file_exists($filename)) {
111 1
            return $filename;
112
        }
113
114
        if (!$this->useIncludePath()) {
115
            throw new RuntimeException(sprintf(
116
                'Filename "%s" cannot be found relative to the working directory',
117
                $filename
118
            ));
119
        }
120
121
        $fromIncludePath = stream_resolve_include_path($filename);
122
        if (!$fromIncludePath) {
123
            throw new RuntimeException(sprintf(
124
                'Filename "%s" cannot be found relative to the working directory or the include_path ("%s")',
125
                $filename,
126
                get_include_path()
127
            ));
128
        }
129
130
        return $fromIncludePath;
131
    }
132
}
133