Passed
Branch master (f496ba)
by stéphane
02:11
created

Loader::onDeepestType()   B

Complexity

Conditions 11
Paths 30

Size

Total Lines 26
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 21
nc 30
nop 4
dl 0
loc 26
rs 7.3166
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\{Node, Builder, Types as T};
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Dallgoot\Yaml\Node. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
Bug introduced by
This use statement conflicts with another class in this namespace, Dallgoot\Yaml\Builder. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
7
8
class Loader
0 ignored issues
show
Coding Style introduced by
Missing class doc comment
Loading history...
9
{
10
    public $errors = [];
11
    //options
12
    public const EXCLUDE_DIRECTIVES = 0001;//DONT include_directive
13
    public const IGNORE_COMMENTS    = 0010;//DONT include_comments
14
    public const EXCEPTIONS_PARSING = 0100;//THROW Exception on parsing Errors
15
    public const NO_OBJECT_FOR_DATE = 1000;//DONT import date strings as dateTime Object
16
    //
17
    private $content;
0 ignored issues
show
Coding Style introduced by
Private member variable "content" must be prefixed with an underscore
Loading history...
18
    private $filePath;
0 ignored issues
show
Coding Style introduced by
Private member variable "filePath" must be prefixed with an underscore
Loading history...
19
    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...
20
    private $options = 0;
0 ignored issues
show
Coding Style introduced by
Private member variable "options" must be prefixed with an underscore
Loading history...
21
    //Exceptions
22
    const INVALID_VALUE        = self::class.": at line %d";
23
    const EXCEPTION_NO_FILE    = self::class.": file '%s' does not exists (or path is incorrect?)";
24
    const EXCEPTION_READ_ERROR = self::class.": file '%s' failed to be loaded (permission denied ?)";
25
    const EXCEPTION_LINE_SPLIT = self::class.": content is not a string(maybe a file error?)";
26
27
    public function __construct($absolutePath = null, $options = null, $debug = 0)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
28
    {
29
        $this->debug = is_int($debug) ? min($debug, 3) : 1;
30
        if (!is_null($options)) {
31
            $this->options = $options;
32
        }
33
        if (!is_null($absolutePath)) {
34
            $this->load($absolutePath);
35
        }
36
    }
37
38
    public function load(String $absolutePath):Loader
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
39
    {
40
        $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...
41
        $this->filePath = $absolutePath;
42
        if (!file_exists($absolutePath)) {
43
            throw new \Exception(sprintf(self::EXCEPTION_NO_FILE, $absolutePath));
44
        }
45
        $adle = "auto_detect_line_endings";
46
        $prevADLE = ini_get($adle);
47
        !$prevADLE && ini_set($adle, "true");
48
        $content = file($absolutePath, FILE_IGNORE_NEW_LINES);
49
        !$prevADLE && ini_set($adle, "false");
50
        if (is_bool($content)) {
51
            throw new \Exception(sprintf(self::EXCEPTION_READ_ERROR, $absolutePath));
52
        }
53
        $this->content = $content;
54
        return $this;
55
    }
56
57
    /**
58
     * Parse Yaml lines into an hierarchy of Node
59
     *
60
     * @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...
61
     * @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...
62
     * @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...
63
     *
64
     * @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...
65
     */
66
    public function parse($strContent = null)
67
    {
68
        $source = $this->content;
69
        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...
70
        //TODO : be more permissive on $strContent values
71
        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...
72
        $previous = $root = new Node();
73
        $emptyLines = [];
74
        $specialTypes = [T::LITTERAL, T::LITTERAL_FOLDED, T::EMPTY];
75
        try {
76
            foreach ($source as $lineNb => $lineString) {
77
                $n = new Node($lineString, $lineNb + 1);//TODO: useful???-> $this->debug && var_dump($n);
78
                $parent  = $previous;
79
                $deepest = $previous->getDeepestNode();
80
                if ($deepest->type === T::PARTIAL) {
81
                    //TODO:verify this edge case
82
                    // if ($n->type === T::KEY && $n->indent === $previous->indent) {
83
                    //     throw new \ParseError(sprintf(self::INVALID_VALUE, $lineNb), 1);
84
                    // }
85
                    $deepest->parse($deepest->value.' '.ltrim($lineString));
86
                } else {
87
                    if (in_array($n->type, $specialTypes)) {
88
                        if ($this->onSpecialType($n, $parent, $previous, $emptyLines)) continue;
1 ignored issue
show
Coding Style introduced by
Inline control structures are discouraged
Loading history...
89
                    }
90
                    foreach ($emptyLines as $key => $node) {
91
                        $node->getParent()->add($node);
92
                    }
93
                    $emptyLines = [];
94
                    if ($n->indent < $previous->indent) {
95
                        $parent = $previous->getParent($n->indent);
96
                    } elseif ($n->indent === $previous->indent) {
97
                        $parent = $previous->getParent();
98
                    } elseif ($n->indent > $previous->indent) {
99
                        if ($this->onDeepestType($n, $parent, $previous, $lineString)) continue;
1 ignored issue
show
Coding Style introduced by
Inline control structures are discouraged
Loading history...
100
                    }
101
                    $parent->add($n);
102
                    $previous = $n;
103
                }
104
            }
105
            if ($this->debug === 2) {
106
                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...
107
                exit(0);
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...
108
            }
109
            $out = Builder::buildContent($root, $this->debug);
110
            return $out;
111
        } catch (\ParseError $pe) {
112
            $message = $pe->getMessage()." on line ".$pe->getLine();
113
            if ($this->options & self::EXCEPTIONS_PARSING) {
114
                var_dump($root);
115
                throw new \Exception($message, 1);
116
            }
117
            $this->errors[] = $message;
118
        } catch (\Error|\Exception $e) {
119
            throw new \Exception($e->getMessage()." for '$this->filePath'", 1);
120
        }
121
    }
122
123
    private function onSpecialType(&$n, &$parent, &$previous, &$emptyLines):bool
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
Coding Style introduced by
Private method name "Loader::onSpecialType" must be prefixed with an underscore
Loading history...
124
    {
125
        $deepest = $previous->getDeepestNode();
126
        switch ($n->type) {
127
            case T::EMPTY:
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
128
                if ($previous->type === T::SCALAR) $emptyLines[] = $n->setParent($previous->getParent());
1 ignored issue
show
Coding Style introduced by
Inline control structures are discouraged
Loading history...
129
                if (in_array($deepest->type, T::$LITTERALS)) $emptyLines[] = $n->setParent($deepest);
1 ignored issue
show
Coding Style introduced by
Inline control structures are discouraged
Loading history...
130
                return true;
131
            case T::LITTERAL://fall through
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
132
            case T::LITTERAL_FOLDED://var_dump($deepest);exit();
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
133
                if ($deepest->type === T::KEY && is_null($deepest->value)) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
134
                    $deepest->add($n);
135
                    $previous = $n;
136
                    return true;
137
                }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
138
            default:
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
139
                return false;
140
        }
141
    }
142
143
    private function onDeepestType(&$n, &$parent, &$previous, $lineString):bool
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
Coding Style introduced by
Private method name "Loader::onDeepestType" must be prefixed with an underscore
Loading history...
144
    {
145
        $deepest = $previous->getDeepestNode();
146
        switch ($deepest->type) {
147
            case T::LITTERAL:
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
148
            case T::LITTERAL_FOLDED:
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
149
                $n->value = trim($lineString);//fall through
150
            case T::REF_DEF://fall through
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
151
            case T::SET_VALUE://fall through
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
152
            case T::TAG:
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
153
                $parent = $deepest;
154
                break;
155
            case T::EMPTY:
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
156
            case T::SCALAR:
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
157
                if ($n->type === T::SCALAR &&
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
158
                    !in_array($deepest->getParent()->type, T::$LITTERALS) ) {
0 ignored issues
show
Coding Style introduced by
Each line in a multi-line IF statement must begin with a boolean operator
Loading history...
Coding Style introduced by
Closing parenthesis of a multi-line IF statement must be on a new line
Loading history...
159
                    $deepest->type = T::SCALAR;
160
                    $deepest->value .= "\n".$n->value;
161
                    return true;
162
                } else {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
163
                    if (!in_array($previous->type, [T::ITEM, T::SET_KEY])) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
164
                        $parent = $deepest->getParent();
165
                    }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
166
                }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
167
        }
168
        return false;
169
    }
170
}
171