Completed
Push — master ( f496ba...7a981c )
by stéphane
02:09
created

Loader   A

Complexity

Total Complexity 40

Size/Duplication

Total Lines 163
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 97
dl 0
loc 163
rs 9.2
c 0
b 0
f 0
wmc 40

5 Methods

Rating   Name   Duplication   Size   Complexity  
D parse() 0 54 16
B onSpecialType() 0 16 7
B onDeepestType() 0 22 7
A load() 0 17 6
A __construct() 0 6 4

How to fix   Complexity   

Complex Class

Complex classes like Loader often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Loader, and based on these observations, apply Extract Interface, too.

1
<?php
2
declare(strict_types=1);
0 ignored issues
show
Coding Style introduced by
Missing file doc comment
Loading history...
3
4
namespace Dallgoot\Yaml;
5
6
use Dallgoot\Yaml as Y;
7
8
class Loader
0 ignored issues
show
Coding Style introduced by
Missing class doc comment
Loading history...
9
{
10
    //public
11
    public $errors = [];
12
13
    public const EXCLUDE_DIRECTIVES = 1;//DONT include_directive
14
    public const IGNORE_COMMENTS    = 2;//DONT include_comments
15
    public const EXCEPTIONS_PARSING = 4;//THROW Exception on parsing Errors
16
    public const NO_OBJECT_FOR_DATE = 8;//DONT import date strings as dateTime Object
17
    //privates
18
    private $content;/* @var null|string */
0 ignored issues
show
Coding Style introduced by
Private member variable "content" must be prefixed with an underscore
Loading history...
19
    private $filePath;/* @var null|string */
0 ignored issues
show
Coding Style introduced by
Private member variable "filePath" must be prefixed with an underscore
Loading history...
20
    private $debug = 0;//TODO: determine levels
0 ignored issues
show
Coding Style introduced by
Private member variable "debug" must be prefixed with an underscore
Loading history...
21
    private $options = 0;/* @var int */
0 ignored issues
show
Coding Style introduced by
Private member variable "options" must be prefixed with an underscore
Loading history...
22
    //Exceptions messages
23
    private const INVALID_VALUE        = self::class.": at line %d";
24
    private const EXCEPTION_NO_FILE    = self::class.": file '%s' does not exists (or path is incorrect?)";
25
    private const EXCEPTION_READ_ERROR = self::class.": file '%s' failed to be loaded (permission denied ?)";
26
    private const EXCEPTION_LINE_SPLIT = self::class.": content is not a string(maybe a file error?)";
27
28
    public function __construct($absolutePath = null, $options = null, $debug = 0)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
29
    {
30
        $this->debug   = is_int($debug)   ? min($debug, 3) : 1;
31
        $this->options = is_int($options) ? $options       : $this->options;
32
        if (is_string($absolutePath)) {
33
            $this->load($absolutePath);
34
        }
35
    }
36
37
    /**
38
     * load a file and save its content as $content
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
39
     *
40
     * @param      string       $absolutePath  The absolute path of a file
3 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter type; 7 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 6
Loading history...
41
     *
42
     * @throws     \Exception   if file don't exist OR reading failed
1 ignored issue
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 5
Loading history...
43
     *
44
     * @return     self  ( returns the same Loader  )
1 ignored issue
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 5
Loading history...
45
     */
46
    public function load(string $absolutePath):Loader
47
    {
48
        $this->debug && var_dump($absolutePath);
1 ignored issue
show
Security Debugging Code introduced by
var_dump($absolutePath) looks like debug code. Are you sure you do not want to remove it?
Loading history...
49
        $this->filePath = $absolutePath;
50
        if (!file_exists($absolutePath)) {
51
            throw new \Exception(sprintf(self::EXCEPTION_NO_FILE, $absolutePath));
52
        }
53
        $adle = "auto_detect_line_endings";
54
        $prevADLE = ini_get($adle);
55
        !$prevADLE && ini_set($adle, "true");
56
        $content = file($absolutePath, FILE_IGNORE_NEW_LINES);
57
        !$prevADLE && ini_set($adle, "false");
58
        if (is_bool($content)) {
59
            throw new \Exception(sprintf(self::EXCEPTION_READ_ERROR, $absolutePath));
60
        }
61
        $this->content = $content;
62
        return $this;
63
    }
64
65
    /**
66
     * Parse Yaml lines into an hierarchy of Node
67
     *
68
     * @param      string       $strContent  The Yaml string or null to parse loaded content
3 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter type; 7 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 6
Loading history...
69
     * @throws     \Exception    if content is not available as $strContent or as $this->content (from file)
1 ignored issue
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 5
Loading history...
70
     * @throws     \ParseError  if any error during parsing or building
1 ignored issue
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 5
Loading history...
71
     *
72
     * @return     array|YamlObject      the hierarchy built an array of YamlObject or just YamlObject
1 ignored issue
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 5
Loading history...
73
     */
74
    public function parse($strContent = null)
75
    {
76
        $source = $this->content;
77
        if (is_null($source)) $source = preg_split("/([^\n\r]+)/um", $strContent, 0, PREG_SPLIT_DELIM_CAPTURE);
1 ignored issue
show
Coding Style introduced by
Inline control structures are discouraged
Loading history...
78
        //TODO : be more permissive on $strContent values
79
        if (!is_array($source)) throw new \Exception(self::EXCEPTION_LINE_SPLIT);
1 ignored issue
show
Coding Style introduced by
Inline control structures are discouraged
Loading history...
80
        $previous = $root = new Node();
81
        $emptyLines = [];
82
        $specialTypes = Y\LITTERALS | Y\BLANK;
1 ignored issue
show
Bug introduced by
The constant Dallgoot\Yaml\Y\BLANK was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
83
        try {
84
            foreach ($source as $lineNb => $lineString) {
85
                $n = new Node($lineString, $lineNb + 1);//TODO: useful???-> $this->debug && var_dump($n);
86
                $parent  = $previous;
87
                $deepest = $previous->getDeepestNode();
88
                if ($deepest->type & Y\PARTIAL) {
0 ignored issues
show
Bug introduced by
The constant Dallgoot\Yaml\Y\PARTIAL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
89
                    //TODO:verify this edge case
90
                    // if ($n->type === Y\KEY && $n->indent === $previous->indent) {
91
                    //     throw new \ParseError(sprintf(self::INVALID_VALUE, $lineNb), 1);
92
                    // }
93
                    $deepest->parse($deepest->value.' '.ltrim($lineString));
94
                } else {
95
                    if ($n->type & $specialTypes) {
96
                        if ($this->onSpecialType($n, $parent, $previous, $emptyLines)) continue;
1 ignored issue
show
Coding Style introduced by
Inline control structures are discouraged
Loading history...
97
                    }
98
                    foreach ($emptyLines as $key => $node) {
99
                        $node->getParent()->add($node);
100
                    }
101
                    $emptyLines = [];
102
                    if ($n->indent < $previous->indent) {
103
                        $parent = $previous->getParent($n->indent);
104
                    } elseif ($n->indent === $previous->indent) {
105
                        $parent = $previous->getParent();
106
                    } elseif ($n->indent > $previous->indent) {
107
                        if ($this->onDeepestType($n, $parent, $previous, $lineString)) continue;
1 ignored issue
show
Coding Style introduced by
Inline control structures are discouraged
Loading history...
108
                    }
109
                    $parent->add($n);
110
                    $previous = $n;
111
                }
112
            }
113
            if ($this->debug === 2) {
0 ignored issues
show
introduced by
The condition $this->debug is always false. If $this->debug can have other possible types, add them to yaml/Loader.php:19
Loading history...
114
                var_dump("\033[33mParsed Structure\033[0m\n", $root);
0 ignored issues
show
Security Debugging Code introduced by
var_dump('Parsed Structure ', $root) looks like debug code. Are you sure you do not want to remove it?
Loading history...
115
                die("Debug of root structure requested (remove debug level to suppress these)");
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
116
            }
117
            $out = Builder::buildContent($root, $this->debug);//var_dump($out);exit();
0 ignored issues
show
Bug introduced by
The type Dallgoot\Yaml\Builder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
118
            return $out;
119
        } catch (\ParseError $pe) {
120
            $message = $pe->getMessage()." on line ".$pe->getLine()." for '$this->filePath'\n";
121
            if ($this->options & self::EXCEPTIONS_PARSING) {
122
                var_dump($root);
123
                throw new \Exception($message, 1);
124
            }
125
            $this->errors[] = $message;
126
        } catch (\Error|\Exception $e) {
127
            throw new \Exception(basename($e->getFile())."(".$e->getLine()."):".$e->getMessage()." for '$this->filePath'\n", 3);
128
        }
129
    }
130
131
    private function onSpecialType(&$n, &$parent, &$previous, &$emptyLines):bool
0 ignored issues
show
Unused Code introduced by
The parameter $parent is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

131
    private function onSpecialType(&$n, /** @scrutinizer ignore-unused */ &$parent, &$previous, &$emptyLines):bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
Private method name "Loader::onSpecialType" must be prefixed with an underscore
Loading history...
Coding Style introduced by
Missing function doc comment
Loading history...
132
    {
133
        $deepest = $previous->getDeepestNode();
134
        if ($n->type & Y\LITTERALS) {
135
            if ($deepest->type & Y\KEY && is_null($deepest->value)) {
1 ignored issue
show
Bug introduced by
The constant Dallgoot\Yaml\Y\KEY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
136
                $deepest->add($n);
137
                $previous = $n;
138
                return true;
139
            }
140
        }
141
        if ($n->type & Y\BLANK) {
1 ignored issue
show
Bug introduced by
The constant Dallgoot\Yaml\Y\BLANK was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
142
            if ($previous->type & Y\SCALAR) $emptyLines[] = $n->setParent($previous->getParent());
1 ignored issue
show
Bug introduced by
The constant Dallgoot\Yaml\Y\SCALAR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Coding Style introduced by
Inline control structures are discouraged
Loading history...
143
            if ($deepest->type & Y\LITTERALS) $emptyLines[] = $n->setParent($deepest);
1 ignored issue
show
Coding Style introduced by
Inline control structures are discouraged
Loading history...
144
            return true;
145
        }
146
        return false;
147
    }
148
149
    private function onDeepestType(&$n, &$parent, &$previous, $lineString):bool
0 ignored issues
show
Coding Style introduced by
Private method name "Loader::onDeepestType" must be prefixed with an underscore
Loading history...
Coding Style introduced by
Missing function doc comment
Loading history...
150
    {
151
        $deepest = $previous->getDeepestNode();
152
        if ($deepest->type & Y\LITTERALS) {
153
            $n->value = trim($lineString);//fall through
154
        }
155
        if ($deepest->type & (Y\LITTERALS | Y\REF_DEF | Y\SET_VALUE | Y\TAG)) {
0 ignored issues
show
Bug introduced by
The constant Dallgoot\Yaml\Y\REF_DEF was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant Dallgoot\Yaml\Y\TAG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant Dallgoot\Yaml\Y\SET_VALUE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
156
            $parent = $deepest;
157
            return false;
158
        }
159
        if ($deepest->type & (Y\BLANK | Y\SCALAR) ) {
1 ignored issue
show
Bug introduced by
The constant Dallgoot\Yaml\Y\SCALAR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant Dallgoot\Yaml\Y\BLANK was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
160
            if ($n->type === Y\SCALAR && ($deepest->getParent()->type & Y\LITTERALS)) {
161
                $deepest->type = Y\SCALAR;
162
                $deepest->value .= "\n".$n->value;
163
                return true;
164
            } else {
165
                if ($previous->type & (Y\ITEM | Y\SET_KEY)) {
0 ignored issues
show
Bug introduced by
The constant Dallgoot\Yaml\Y\SET_KEY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant Dallgoot\Yaml\Y\ITEM was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
166
                    $parent = $deepest->getParent();
167
                }
168
            }
169
        }
170
        return false;
171
    }
172
}
173