Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
9 / 9
CRAP
100.00% covered (success)
100.00%
1 / 1
Document
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
9 / 9
20
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getDoctype
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCharset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getContentType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setDoctype
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
9
 setCharset
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setContentType
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 render
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <nick@popphp.org>
8 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Dom;
16
17/**
18 * Dom class
19 *
20 * @category   Pop
21 * @package    Pop\Dom
22 * @author     Nick Sagona, III <nick@popphp.org>
23 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
24 * @license    https://www.popphp.org/license     New BSD License
25 * @version    5.0.0
26 */
27class Document extends AbstractNode
28{
29
30    /**
31     * Constant to use the XML doctype
32     * @var string
33     */
34    const XML = 'XML';
35
36    /**
37     * Constant to use the HTML doctype
38     * @var string
39     */
40    const HTML = 'HTML';
41
42    /**
43     * Constant to use the XML doctype, RSS content-type
44     * @var string
45     */
46    const RSS = 'RSS';
47
48    /**
49     * Constant to use the XML doctype, Atom content-type
50     * @var string
51     */
52    const ATOM = 'ATOM';
53
54    /**
55     * Document type
56     * @var string
57     */
58    protected string $doctype = 'XML';
59
60    /**
61     * Document content type
62     * @var string
63     */
64    protected string $contentType = 'application/xml';
65
66    /**
67     * Document charset
68     * @var string
69     */
70    protected string $charset = 'utf-8';
71
72    /**
73     * Document doctypes
74     * @var array
75     */
76    protected static array $doctypes = [
77        'XML'  => "<?xml version=\"1.0\" encoding=\"[{charset}]\"?>\n",
78        'HTML' =>"<!DOCTYPE html>\n"
79    ];
80
81    /**
82     * Constructor
83     *
84     * Instantiate the document object
85     *
86     * @param  string  $doctype
87     * @param  ?Child  $childNode
88     * @param  ?string $indent
89     * @throws Exception
90     */
91    public function __construct(string $doctype = 'XML', ?Child $childNode = null, ?string $indent = null)
92    {
93        $this->setDoctype($doctype);
94
95        if ($childNode !== null) {
96            $this->addChild($childNode);
97        }
98        if ($indent !== null) {
99            $this->setIndent($indent);
100        }
101    }
102
103    /**
104     * Return the document type.
105     *
106     * @return string
107     */
108    public function getDoctype(): string
109    {
110        return str_replace('[{charset}]', $this->charset, Document::$doctypes[$this->doctype]);
111    }
112
113    /**
114     * Return the document charset
115     *
116     * @return string
117     */
118    public function getCharset(): string
119    {
120        return $this->charset;
121    }
122
123    /**
124     * Return the document charset
125     *
126     * @return string
127     */
128    public function getContentType(): string
129    {
130        return $this->contentType;
131    }
132
133    /**
134     * Set the document type
135     *
136     * @param  string $doctype
137     * @throws Exception
138     * @return Document
139     */
140    public function setDoctype(string $doctype): Document
141    {
142        $doctype = strtoupper($doctype);
143
144        if (($doctype != self::XML) && ($doctype != self::HTML) && ($doctype != self::RSS) && ($doctype != self::ATOM)) {
145            throw new Exception('Error: Incorrect document type');
146        }
147
148        switch ($doctype) {
149            case 'XML':
150                $this->doctype     = self::XML;
151                $this->contentType = 'application/xml';
152                break;
153            case 'HTML':
154                $this->doctype     = self::HTML;
155                $this->contentType = 'text/html';
156                break;
157            case 'RSS':
158                $this->doctype     = self::XML;
159                $this->contentType = 'application/rss+xml';
160                break;
161            case 'ATOM':
162                $this->doctype     = self::XML;
163                $this->contentType = 'application/atom+xml';
164                break;
165        }
166
167        return $this;
168    }
169
170    /**
171     * Set the document charset
172     *
173     * @param  string $char
174     * @return Document
175     */
176    public function setCharset(string $char): Document
177    {
178        $this->charset = $char;
179        return $this;
180    }
181
182    /**
183     * Set the document charset
184     *
185     * @param  string $content
186     * @return Document
187     */
188    public function setContentType(string $content): Document
189    {
190        $this->contentType = $content;
191        return $this;
192    }
193
194    /**
195     * Render the document and its child elements
196     *
197     * @return string
198     */
199    public function render(): string
200    {
201        $this->output = str_replace('[{charset}]', $this->charset, Document::$doctypes[$this->doctype]);
202
203        foreach ($this->childNodes as $child) {
204            $this->output .= $child->render(0, $this->indent);
205        }
206
207        return $this->output;
208    }
209
210    /**
211     * Render Dom object to string
212     *
213     * @return string
214     */
215    public function __toString(): string
216    {
217        return $this->render();
218    }
219
220}