Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
88.00% |
44 / 50 |
|
20.00% |
1 / 5 |
CRAP | |
0.00% |
0 / 1 |
XMLSchema | |
88.00% |
44 / 50 |
|
20.00% |
1 / 5 |
25.00 | |
0.00% |
0 / 1 |
parseSchemaUrl | |
100.00% |
18 / 18 |
|
100.00% |
1 / 1 |
10 | |||
getLocalSchema | |
88.89% |
8 / 9 |
|
0.00% |
0 / 1 |
2.01 | |||
getSchemaFilePath | |
80.00% |
4 / 5 |
|
0.00% |
0 / 1 |
4.13 | |||
accessDefinitionsDir | |
75.00% |
3 / 4 |
|
0.00% |
0 / 1 |
2.06 | |||
accessSchemaCache | |
78.57% |
11 / 14 |
|
0.00% |
0 / 1 |
6.35 |
1 | <?php |
2 | /** @noinspection PhpUnhandledExceptionInspection */ |
3 | declare(strict_types=1); |
4 | |
5 | class XMLSchema { |
6 | // TODO use defined class instead of plain array |
7 | static function parseSchemaUrl(string $schemaUri): ?array { |
8 | $regex = '#^(http)?.*?((\d+).(\d+).(\d+)(-\S*)?)?/definitions/v?o?_?(\S*).xsd$#'; |
9 | preg_match_all($regex, $schemaUri, $matches, PREG_SET_ORDER); |
10 | |
11 | if (!count($matches)) { |
12 | return null; |
13 | } |
14 | |
15 | $urlParts = $matches[0]; |
16 | |
17 | $schemaData = [ |
18 | "isExternal" => ($urlParts[1] === 'http') && isset($urlParts[2]), |
19 | "version" => $urlParts[2] ?? '', |
20 | "mayor" => isset($urlParts[3]) ? (int) $urlParts[3] : 0, |
21 | "minor" => isset($urlParts[4]) ? (int) $urlParts[4] : 0, |
22 | "patch" => isset($urlParts[5]) ? (int) $urlParts[5] : 0, |
23 | "label" => isset($urlParts[6]) ? substr($urlParts[6], 1) : '', |
24 | "type" => $urlParts[7] ?? '', |
25 | "uri" => $schemaUri |
26 | ]; |
27 | |
28 | if ($schemaData['version'] and $schemaData['type'] and ($schemaData['version'] === SystemConfig::$system_version)) { |
29 | return XMLSchema::getLocalSchema($schemaData['type']); |
30 | } |
31 | |
32 | return $schemaData; |
33 | } |
34 | |
35 | static function getLocalSchema(string $type): array { |
36 | if (!file_exists(ROOT_DIR . "/definitions/vo_$type.xsd")) { |
37 | throw new Exception("Unknown XML type: `$type`"); |
38 | } |
39 | |
40 | $currentVersion = SystemConfig::$system_version; |
41 | $schemaData = Version::split($currentVersion); |
42 | $schemaData["version"] = $currentVersion; |
43 | $schemaData["isExternal"] = false; |
44 | $schemaData["type"] = $type; |
45 | $schemaData["uri"] = false; |
46 | |
47 | return $schemaData; |
48 | } |
49 | |
50 | static function getSchemaFilePath(?array $schemaData): string { |
51 | if (!$schemaData) { |
52 | return ''; |
53 | } |
54 | |
55 | if (!SystemConfig::$debug_allowExternalXmlSchema or !$schemaData['isExternal']) { |
56 | return XMLSchema::accessDefinitionsDir($schemaData); |
57 | } else { |
58 | return XMLSchema::accessSchemaCache($schemaData); |
59 | } |
60 | } |
61 | |
62 | private static function accessDefinitionsDir($schemaData): string { |
63 | $filePath = ROOT_DIR . "/definitions/vo_{$schemaData['type']}.xsd"; |
64 | |
65 | if (file_exists($filePath)) { |
66 | return $filePath; |
67 | } |
68 | |
69 | return ""; |
70 | } |
71 | |
72 | private static function accessSchemaCache(array $schemaData): string { |
73 | if (!$schemaData['isExternal']) { |
74 | return ''; |
75 | } |
76 | |
77 | $folder = DATA_DIR . "/.schemas/{$schemaData['type']}/v{$schemaData['mayor']}/"; |
78 | $fileName = "{$schemaData['type']}-{$schemaData['version']}.xsd"; |
79 | |
80 | if (file_exists("$folder$fileName")) { |
81 | if (!filesize("$folder$fileName")) { |
82 | return ""; |
83 | } |
84 | |
85 | return "$folder$fileName"; |
86 | } |
87 | |
88 | Folder::createPath($folder); |
89 | |
90 | if (!is_writable($folder)) { |
91 | throw new Exception("`$folder` is not writeable!"); |
92 | } |
93 | |
94 | $fileContent = ExternalFile::download($schemaData['uri']); |
95 | |
96 | file_put_contents("$folder$fileName", $fileContent); |
97 | |
98 | return $fileContent ? "$folder$fileName" : ''; |
99 | } |
100 | } |