Completed
Pull Request — master (#227)
by Alex
09:20
created

AtomODataReader::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 6
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 8
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
6
namespace POData\Readers\Atom;
7
8
use POData\Common\MimeTypes;
9
use POData\Common\ODataConstants;
10
use POData\ObjectModel\ODataEntry;
11
use POData\ObjectModel\ODataFeed;
12
use POData\Readers\Atom\Processors\BaseNodeHandler;
13
use POData\Readers\Atom\Processors\EntryProcessor;
14
use POData\Readers\Atom\Processors\FeedProcessor;
15
use POData\Readers\IODataReader;
16
use SplStack;
17
18
class AtomODataReader implements IODataReader
19
{
20
    /**
21
     * XmlParser.
22
     *
23
     * @var resource
24
     */
25
    private $parser;
26
    /**
27
     * @var SplStack|BaseNodeHandler[]
28
     */
29
    private $stack;
30
    /**
31
     * @var ODataFeed|ODataEntry
32
     */
33
    private $objectModel = [];
34
35
    public function __construct()
36
    {
37
        $this->parser = xml_parser_create_ns('UTF-8', '|');
38
        xml_set_object($this->parser, $this);
39
        xml_set_element_handler($this->parser, [$this, 'tagOpen'], [$this, 'tagClose']);
40
        xml_set_character_data_handler($this->parser, [$this, 'characterData']);
41
        xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
42
        $this->stack = new SplStack();
43
    }
44
45
    public function __destruct()
46
    {
47
        xml_parser_free($this->parser);
48
    }
49
50
    public function read($data)
51
    {
52
        xml_parse($this->parser, $data, true);
53
        return $this->objectModel;
54
    }
55
56
    public function characterData($parser, $data)
57
    {
58
        if ($this->stack->isEmpty()) {
59
            throw new \ParseError('encountered character data outside of xml tag');
60
        }
61
        $this->stack->top()->handleCharacterData($data);
62
    }
63
64
    public function tagOpen($parser, $tag, $attributes)
65
    {
66
        switch (strtolower($tag)) {
67
            case strtolower(ODataConstants::ATOM_NAMESPACE . '|' . ODataConstants::ATOM_FEED_ELEMENT_NAME):
68
                $this->stack->push(new FeedProcessor());
69
                break;
70
            case strtolower(ODataConstants::ATOM_NAMESPACE . '|' . ODataConstants::ATOM_ENTRY_ELEMENT_NAME):
71
                $this->stack->push(new EntryProcessor());
72
                break;
73
            default:
74
                if ($this->stack->isEmpty()) {
75
                    throw new \ParseError(sprintf('encountered node %s while not in a feed or a stack', $tag));
76
                }
77
                list($namespsace, $name) = explode('|', $tag);
78
                $this->stack->top()->handleStartNode($namespsace, $name, $attributes);
79
        }
80
    }
81
82
    public function tagClose($parser, $tag)
83
    {
84
        switch (strtolower($tag)) {
85
            case strtolower(ODataConstants::ATOM_NAMESPACE . '|' . ODataConstants::ATOM_FEED_ELEMENT_NAME):
86
            case strtolower(ODataConstants::ATOM_NAMESPACE . '|' . ODataConstants::ATOM_ENTRY_ELEMENT_NAME):
87
                $process = $this->stack->pop();
88
                if ($this->stack->isEmpty()) {
89
                    $this->objectModel = $process->getObjetModelObject();
90
                } else {
91
                    $this->stack->top()->handleChildComplete($process->getObjetModelObject());
92
                }
93
                break;
94
            default:
95
                if ($this->stack->isEmpty()) {
96
                    throw new \ParseError('encountered node %s while not in a feed or a stack');
97
                }
98
                list($namespsace, $name) = explode('|', $tag);
99
                $this->stack->top()->handleEndNode($namespsace, $name);
100
        }
101
    }
102
103
    public function canHandle(\POData\Common\Version $responseVersion, $contentType)
104
    {
105
        return MimeTypes::MIME_APPLICATION_ATOM == $contentType || MimeTypes::MIME_APPLICATION_XML === $contentType;
106
    }
107
}
108