xref: /webtrees/app/Report/ReportParserBase.php (revision 3976b4703df669696105ed6b024b96d433c8fbdb)
1ef0d468bSGreg Roach<?php
2*3976b470SGreg Roach
3ef0d468bSGreg Roach/**
4ef0d468bSGreg Roach * webtrees: online genealogy
58fcd0d32SGreg Roach * Copyright (C) 2019 webtrees development team
6ef0d468bSGreg Roach * This program is free software: you can redistribute it and/or modify
7ef0d468bSGreg Roach * it under the terms of the GNU General Public License as published by
8ef0d468bSGreg Roach * the Free Software Foundation, either version 3 of the License, or
9ef0d468bSGreg Roach * (at your option) any later version.
10ef0d468bSGreg Roach * This program is distributed in the hope that it will be useful,
11ef0d468bSGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
12ef0d468bSGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13ef0d468bSGreg Roach * GNU General Public License for more details.
14ef0d468bSGreg Roach * You should have received a copy of the GNU General Public License
15ef0d468bSGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
16ef0d468bSGreg Roach */
17e7f56f2aSGreg Roachdeclare(strict_types=1);
18e7f56f2aSGreg Roach
1976692c8bSGreg Roachnamespace Fisharebest\Webtrees\Report;
20ef0d468bSGreg Roach
21208e9f76SGreg Roachuse DomainException;
227774ce41SGreg Roachuse Exception;
23299d100dSGreg Roach
24ef0d468bSGreg Roach/**
25ef0d468bSGreg Roach * Class ReportParserBase
26ef0d468bSGreg Roach */
27c1010edaSGreg Roachclass ReportParserBase
28c1010edaSGreg Roach{
29ef0d468bSGreg Roach    /** @var resource The XML parser */
30a6f13a4aSGreg Roach    protected $xml_parser;
31ef0d468bSGreg Roach
32ef0d468bSGreg Roach    /** @var string Text contents of tags */
33ef0d468bSGreg Roach    protected $text = '';
34ef0d468bSGreg Roach
35ef0d468bSGreg Roach    /**
36ef0d468bSGreg Roach     * Create a parser for a report
37ef0d468bSGreg Roach     *
38ef0d468bSGreg Roach     * @param string $report The XML filename
397774ce41SGreg Roach     *
407774ce41SGreg Roach     * @throws Exception
41ef0d468bSGreg Roach     */
4276f666f4SGreg Roach    public function __construct(string $report)
43c1010edaSGreg Roach    {
44ef0d468bSGreg Roach        $this->xml_parser = xml_parser_create();
458a4ee39cSGreg Roach
46ef0d468bSGreg Roach        xml_parser_set_option($this->xml_parser, XML_OPTION_CASE_FOLDING, false);
478a4ee39cSGreg Roach
488a4ee39cSGreg Roach        xml_set_element_handler(
498a4ee39cSGreg Roach            $this->xml_parser,
50af14d238SGreg Roach            function ($parser, string $name, array $attrs): void {
518a4ee39cSGreg Roach                $this->startElement($parser, $name, $attrs);
528a4ee39cSGreg Roach            },
53af14d238SGreg Roach            function ($parser, string $name): void {
548a4ee39cSGreg Roach                $this->endElement($parser, $name);
558a4ee39cSGreg Roach            }
568a4ee39cSGreg Roach        );
578a4ee39cSGreg Roach
588a4ee39cSGreg Roach        xml_set_character_data_handler(
598a4ee39cSGreg Roach            $this->xml_parser,
609d454b6bSGreg Roach            function ($parser, string $data): void {
618a4ee39cSGreg Roach                $this->characterData($parser, $data);
628a4ee39cSGreg Roach            }
638a4ee39cSGreg Roach        );
64ef0d468bSGreg Roach
65e364afe4SGreg Roach        $fp = fopen($report, 'rb');
668a4ee39cSGreg Roach
677774ce41SGreg Roach        if ($fp === false) {
687774ce41SGreg Roach            throw new Exception('Cannot open ' . $report);
697774ce41SGreg Roach        }
707774ce41SGreg Roach
71e364afe4SGreg Roach        while ($data = fread($fp, 4096)) {
72ef0d468bSGreg Roach            if (!xml_parse($this->xml_parser, $data, feof($fp))) {
73208e9f76SGreg Roach                throw new DomainException(sprintf(
74ef0d468bSGreg Roach                    'XML error: %s at line %d',
75ef0d468bSGreg Roach                    xml_error_string(xml_get_error_code($this->xml_parser)),
76ef0d468bSGreg Roach                    xml_get_current_line_number($this->xml_parser)
77ef0d468bSGreg Roach                ));
78ef0d468bSGreg Roach            }
79ef0d468bSGreg Roach        }
80ef0d468bSGreg Roach
817774ce41SGreg Roach        fclose($fp);
827774ce41SGreg Roach
83ef0d468bSGreg Roach        xml_parser_free($this->xml_parser);
84ef0d468bSGreg Roach    }
85ef0d468bSGreg Roach
86ef0d468bSGreg Roach    /**
87ef0d468bSGreg Roach     * XML handler for an opening (or self-closing) tag.
88ef0d468bSGreg Roach     *
89ef0d468bSGreg Roach     * @param resource $parser The resource handler for the xml parser
90ef0d468bSGreg Roach     * @param string   $name   The name of the xml element parsed
91ef0d468bSGreg Roach     * @param string[] $attrs  An array of key value pairs for the attributes
9218d7a90dSGreg Roach     *
9318d7a90dSGreg Roach     * @return void
94ef0d468bSGreg Roach     */
95af14d238SGreg Roach    protected function startElement($parser, string $name, array $attrs): void
96c1010edaSGreg Roach    {
97a6f13a4aSGreg Roach        $method = $name . 'StartHandler';
98208e9f76SGreg Roach
99ef0d468bSGreg Roach        if (method_exists($this, $method)) {
100ef0d468bSGreg Roach            $this->$method($attrs);
101ef0d468bSGreg Roach        }
102ef0d468bSGreg Roach    }
103ef0d468bSGreg Roach
104ef0d468bSGreg Roach    /**
105ef0d468bSGreg Roach     * XML handler for a closing tag.
106ef0d468bSGreg Roach     *
107ef0d468bSGreg Roach     * @param resource $parser the resource handler for the xml parser
108ef0d468bSGreg Roach     * @param string   $name   the name of the xml element parsed
10918d7a90dSGreg Roach     *
11018d7a90dSGreg Roach     * @return void
111ef0d468bSGreg Roach     */
112af14d238SGreg Roach    protected function endElement($parser, string $name): void
113c1010edaSGreg Roach    {
114a6f13a4aSGreg Roach        $method = $name . 'EndHandler';
115208e9f76SGreg Roach
116ef0d468bSGreg Roach        if (method_exists($this, $method)) {
117ef0d468bSGreg Roach            $this->$method();
118ef0d468bSGreg Roach        }
119ef0d468bSGreg Roach    }
120ef0d468bSGreg Roach
121ef0d468bSGreg Roach    /**
122ef0d468bSGreg Roach     * XML handler for character data.
123ef0d468bSGreg Roach     *
124ef0d468bSGreg Roach     * @param resource $parser The resource handler for the xml parser
125ef0d468bSGreg Roach     * @param string   $data   The name of the xml element parsed
12618d7a90dSGreg Roach     *
12718d7a90dSGreg Roach     * @return void
128ef0d468bSGreg Roach     */
129af14d238SGreg Roach    protected function characterData($parser, $data): void
130c1010edaSGreg Roach    {
131ef0d468bSGreg Roach        $this->text .= $data;
132ef0d468bSGreg Roach    }
133ef0d468bSGreg Roach}
134