Issues (57)

src/SplitProfile.php (2 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Koriym\AppStateDiagram;
6
7
use Koriym\AppStateDiagram\Exception\AlpsFileNotReadableException;
8
use Koriym\AppStateDiagram\Exception\InvalidAlpsException;
9
use Koriym\XmlLoader\XmlLoader;
10
use Seld\JsonLint\ParsingException;
11
use SplFileInfo;
12
use stdClass;
13
use Throwable;
14
15
use function assert;
16
use function count;
17
use function dirname;
18
use function file_get_contents;
19
use function is_array;
20
use function is_object;
21
use function is_string;
22
use function json_encode;
23
use function property_exists;
24
use function sprintf;
25
use function xmlToArray;
26
27
use const JSON_PRETTY_PRINT;
28
29
final class SplitProfile
30
{
31
    /** @var array<string, array{0: object, 1: list<stdClass>}> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string, array{0: o...ct, 1: list<stdClass>}> at position 12 could not be parsed: Expected '}' at position 12, but found 'list'.
Loading history...
32
    private static $instance;
33
34
    /** @var XmlLoader */
35
    private $xmlLoader;
36
37
    public function __construct()
38
    {
39
        $this->xmlLoader = new XmlLoader();
40
    }
41
42
    /**
43
     * @return array{0: object, 1: list<stdClass>}
0 ignored issues
show
Documentation Bug introduced by
The doc comment array{0: object, 1: list<stdClass>} at position 8 could not be parsed: Expected '}' at position 8, but found 'list'.
Loading history...
44
     *
45
     * @throws ParsingException
46
     */
47
    public function __invoke(string $alpsFile): array
48
    {
49
        if (isset(self::$instance[$alpsFile])) {
50
            return self::$instance[$alpsFile];
51
        }
52
53
        $profile = $this->getJson($alpsFile);
54
        if (! property_exists($profile, 'alps') || ! is_object($profile->alps)) {
55
            throw new InvalidAlpsException($alpsFile);
56
        }
57
58
        if (! property_exists($profile->alps, 'descriptor') || ! is_array($profile->alps->descriptor)) {
59
            throw new InvalidAlpsException($alpsFile);
60
        }
61
62
        $descriptors = $profile->alps->descriptor;
63
        foreach ($descriptors as $descriptor) {
64
            assert($descriptor instanceof stdClass);
65
        }
66
67
        /** @var list<stdClass> $descriptors */
68
        self::$instance[$alpsFile] = [$profile, $descriptors];
69
70
        return self::$instance[$alpsFile];
71
    }
72
73
    private function getJson(string $alpsFile): object
74
    {
75
        return (new JsonDecode())($this->getJsonString($alpsFile));
76
    }
77
78
    private function getJsonString(string $alpsFile): string
79
    {
80
        $isXml = (new SplFileInfo($alpsFile))->getExtension() === 'xml';
81
        try {
82
            $fileContent = (string) file_get_contents($alpsFile);
83
        } catch (Throwable $e) {
84
            throw new AlpsFileNotReadableException(sprintf('%s: %s', $e->getMessage(), $alpsFile));
85
        }
86
87
        if (! $isXml) {
88
            return $fileContent;
89
        }
90
91
        $simpleXml = ($this->xmlLoader)($alpsFile, dirname(__DIR__) . '/alps.xsd');
92
        $array = xmlToArray($simpleXml, ['attributePrefix' => '', 'textContent' => 'value', 'autoText' => true, 'alwaysArray' => ['descriptor']]);
93
94
        if (! isset($array['alps']['descriptor'])) {
95
            assert(is_array($array['alps']));
96
            $array['alps']['descriptor'] = [];
97
        }
98
99
        $descriptor = $array['alps']['descriptor'];
100
        assert(is_array($descriptor));
101
102
        if (count($descriptor) === 1 && isset($descriptor[0]) && $descriptor[0] === []) {
103
            $array['alps']['descriptor'] = [];
104
        }
105
106
        if (isset($array['alps']['doc']) && is_string($array['alps']['doc'])) {
107
            $array['alps']['doc'] = ['value' => $array['alps']['doc']];
108
        }
109
110
        return (string) json_encode($array, JSON_PRETTY_PRINT);
111
    }
112
}
113