Completed
Push — master ( ab7ebf...740609 )
by Grégoire
02:23
created

XmlFile::extractParameters()   B

Complexity

Conditions 10
Paths 14

Size

Total Lines 29
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 10.0145

Importance

Changes 0
Metric Value
cc 10
eloc 19
c 0
b 0
f 0
nc 14
nop 2
dl 0
loc 29
ccs 18
cts 19
cp 0.9474
crap 10.0145
rs 7.6666

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
3
declare(strict_types=1);
4
5
namespace Doctrine\Migrations\Configuration\Configuration;
6
7
use Doctrine\Migrations\Configuration\Configuration;
8
use Doctrine\Migrations\Configuration\Configuration\Exception\XmlNotValid;
9
use Doctrine\Migrations\Configuration\Exception\FileNotFound;
10
use Doctrine\Migrations\Tools\BooleanStringFormatter;
11
use DOMDocument;
12
use SimpleXMLElement;
13
use const DIRECTORY_SEPARATOR;
14
use const LIBXML_NOCDATA;
15
use function assert;
16
use function file_exists;
17
use function file_get_contents;
18
use function libxml_clear_errors;
19
use function libxml_use_internal_errors;
20
use function simplexml_load_string;
21
use function strtr;
22
23
final class XmlFile extends ConfigurationFile
24
{
25 10
    public function getConfiguration() : Configuration
26
    {
27 10
        if (! file_exists($this->file)) {
28 1
            throw FileNotFound::new($this->file);
29
        }
30
31 9
        $this->validateXml($this->file);
32
33 6
        $rawXML = file_get_contents($this->file);
34 6
        assert($rawXML !== false);
35
36 6
        $root = simplexml_load_string($rawXML, SimpleXMLElement::class, LIBXML_NOCDATA);
37 6
        assert($root !== false);
38
39 6
        $config = $this->extractParameters($root, true);
40
41 6
        if (isset($config['all_or_nothing'])) {
42 2
            $config['all_or_nothing'] = BooleanStringFormatter::toBoolean(
43 2
                $config['all_or_nothing'],
44 2
                false
45
            );
46
        }
47 6
        if (isset($config['migrations_paths'])) {
48 3
            $config['migrations_paths'] = $this->getDirectoriesRelativeToFile(
49 3
                $config['migrations_paths'],
50 3
                $this->file
51
            );
52
        }
53
54 6
        return (new ConfigurationArray($config))->getConfiguration();
55
    }
56
57
    /**
58
     * @return mixed[]
59
     */
60 6
    private function extractParameters(SimpleXMLElement $root, bool $loopOverNodes) : array
61
    {
62 6
        $config = [];
63
64 6
        $itemsToCheck = $loopOverNodes ? $root->children() : $root->attributes();
65
66 6
        if (! ($itemsToCheck instanceof SimpleXMLElement)) {
0 ignored issues
show
introduced by
$itemsToCheck is always a sub-type of SimpleXMLElement.
Loading history...
67
            return $config;
68
        }
69 6
        foreach ($itemsToCheck as $node) {
70 6
            $nodeName = strtr($node->getName(), '-', '_');
71 6
            if ($nodeName === 'migrations_paths') {
72 3
                $config['migrations_paths'] = [];
73 3
                foreach ($node->{'path'} as $pathNode) {
74 3
                    $config['migrations_paths'][(string) $pathNode['namespace']] = (string) $pathNode;
75
                }
76 5
            } elseif ($nodeName === 'storage' && $node->{'table-storage'} instanceof SimpleXMLElement) {
77 2
                $config['table_storage'] = $this->extractParameters($node->{'table-storage'}, false);
78 5
            } elseif ($nodeName === 'migrations') {
79 2
                $config['migrations'] = [];
80 2
                foreach ($node->{'migration'} as $pathNode) {
81 2
                    $config['migrations'][] = (string) $pathNode;
82
                }
83
            } else {
84 5
                $config[$nodeName] = (string) $node;
85
            }
86
        }
87
88 6
        return $config;
89
    }
90
91 9
    private function validateXml(string $file) : void
92
    {
93
        try {
94 9
            libxml_use_internal_errors(true);
95
96 9
            $xml = new DOMDocument();
97
98 9
            if ($xml->load($file) === false) {
99 1
                throw XmlNotValid::malformed();
100
            }
101
102 8
            $xsdPath = __DIR__ . DIRECTORY_SEPARATOR . 'XML' . DIRECTORY_SEPARATOR . 'configuration.xsd';
103
104 8
            if ($xml->schemaValidate($xsdPath) === false) {
105 2
                throw XmlNotValid::failedValidation();
106
            }
107 6
        } finally {
108 9
            libxml_clear_errors();
109 9
            libxml_use_internal_errors(false);
110
        }
111 6
    }
112
}
113