Completed
Push — master ( 92c5ca...d25621 )
by Gerben
02:12
created

Validator::getFileContent()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 3
nc 2
nop 1
crap 3
1
<?php declare(strict_types=1);
2
3
namespace Hyperized\Xml;
4
5
use DOMDocument;
6
use ErrorException;
7
use Hyperized\Xml\Constants\ErrorMessages;
8
use Hyperized\Xml\Constants\Strings;
9
use Hyperized\Xml\Exceptions\FileCouldNotBeOpenedException;
10
use Hyperized\Xml\Exceptions\InvalidXml;
11
12
13
/**
14
 * Class Validator
15
 *
16
 * @package Hyperized\Xml
17
 * Based on: http://stackoverflow.com/a/30058598/1757763
18
 */
19
final class Validator implements ValidatorInterface
20
{
21
    /**
22
     * @var string
23
     */
24
    private $version = Strings::VERSION;
25
    /**
26
     * @var string
27
     */
28
    private $encoding = Strings::UTF_8;
29
30
31
    /**
32
     * @param  string      $xmlPath
33
     * @param  string|null $xsdPath
34
     * @return bool
35
     * @throws FileCouldNotBeOpenedException
36
     * @throws InvalidXml
37
     */
38 12
    public function isXMLFileValid(string $xmlPath, string $xsdPath = null): bool
39
    {
40 12
        return $this->isXMLStringValid(self::getFileContent($xmlPath), $xsdPath);
41
    }
42
43
    /**
44
     * @param  string      $xml
45
     * @param  string|null $xsdPath
46
     * @return bool
47
     * @throws InvalidXml
48
     */
49 16
    public function isXMLStringValid(string $xml, string $xsdPath = null): bool
50
    {
51 16
        if (\is_string($xsdPath)) {
52 4
            return $this->isXMLValid($xml, $xsdPath);
53
        }
54 12
        return $this->isXMLValid($xml);
55
    }
56
57
    /**
58
     * @param  string      $xmlContent
59
     * @param  string|null $xsdPath
60
     * @return bool
61
     * @throws InvalidXml
62
     */
63 16
    private function isXMLValid(string $xmlContent, string $xsdPath = null): bool
64
    {
65 16
        self::checkEmptyWhenTrimmed($xmlContent);
66
67 12
        libxml_use_internal_errors(true);
68
69 12
        $document = new DOMDocument($this->version, $this->encoding);
70 12
        $document->loadXML($xmlContent);
71 12
        if (isset($xsdPath)) {
72 4
            $document->schemaValidate($xsdPath);
73
        }
74
75 12
        $errors = libxml_get_errors();
76 12
        libxml_clear_errors();
77 12
        self::parseErrors($errors);
78 6
        return true;
79
    }
80
81
    /**
82
     * @param  string $xmlContent
83
     * @throws InvalidXml
84
     */
85 16
    private static function checkEmptyWhenTrimmed(string $xmlContent): void
86
    {
87 16
        if (trim($xmlContent) === '') {
88 4
            throw new InvalidXml(ErrorMessages::XML_EMPTY_TRIMMED);
89
        }
90 12
    }
91
92
    /**
93
     * @param  array $errors
94
     * @throws InvalidXml
95
     */
96 12
    private static function parseErrors(array $errors): void
97
    {
98 12
        if (!empty($errors)) {
99 6
            $return = [];
100 6
            foreach ($errors as $error) {
101 6
                $return[] = trim($error->message);
102
            }
103 6
            throw new InvalidXml(implode(Strings::NEW_LINE, $return));
104
        }
105 6
    }
106
107
    /**
108
     * @param  string $fileName
109
     * @return string
110
     * @throws FileCouldNotBeOpenedException
111
     */
112 12
    private static function getFileContent(string $fileName): string
113
    {
114
        try {
115 12
            $contents = file_get_contents($fileName);
116 2
        } catch (\Exception $exception) {
117 2
            throw new FileCouldNotBeOpenedException(ErrorMessages::NO_FILE_CONTENTS);
118
        }
119 10
        return '' ?: $contents;
120
    }
121
122
    /**
123
     * @return string
124
     */
125 2
    public function getVersion(): string
126
    {
127 2
        return $this->version;
128
    }
129
130
    /**
131
     * @param string $version
132
     */
133 2
    public function setVersion(string $version): void
134
    {
135 2
        $this->version = $version;
136 2
    }
137
138
    /**
139
     * @return string
140
     */
141 2
    public function getEncoding(): string
142
    {
143 2
        return $this->encoding;
144
    }
145
146
    /**
147
     * @param string $encoding
148
     */
149 2
    public function setEncoding(string $encoding): void
150
    {
151 2
        $this->encoding = $encoding;
152 2
    }
153
}
154