Completed
Push — master ( 1a86ff...82b6ab )
by ignace nyamagana
03:32
created

HTMLConverter::appendTableHeaderSection()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 3
dl 0
loc 20
ccs 12
cts 12
cp 1
crap 3
rs 9.6
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * League.Csv (https://csv.thephpleague.com)
5
 *
6
 * (c) Ignace Nyamagana Butera <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace League\Csv;
15
16
use DOMDocument;
17
use DOMElement;
18
use DOMException;
19
use Traversable;
20
use function preg_match;
21
22
/**
23
 * Converts tabular data into an HTML Table string.
24
 */
25
class HTMLConverter
26
{
27
    /**
28
     * table class attribute value.
29
     *
30
     * @var string
31
     */
32
    protected $class_name = 'table-csv-data';
33
34
    /**
35
     * table id attribute value.
36
     *
37
     * @var string
38
     */
39
    protected $id_value = '';
40
41
    /**
42
     * @var XMLConverter
43
     */
44
    protected $xml_converter;
45
46
    /**
47
     * New Instance.
48
     */
49 6
    public function __construct()
50
    {
51 6
        $this->xml_converter = (new XMLConverter())
52 6
            ->rootElement('table')
53 6
            ->recordElement('tr')
54 6
            ->fieldElement('td')
55
        ;
56 6
    }
57
58
    /**
59
     * Convert an Record collection into a DOMDocument.
60
     *
61
     * @param array|Traversable $records       The tabular data collection
62
     * @param string[]          $header_record An optional array of headers to output to the table using `<thead>` and `<th>` elements
63
     * @param string[]          $footer_record An optional array of footers to output to the table using `<tfoot>` and `<th>` elements
64
     */
65 12
    public function convert($records, array $header_record = [], array $footer_record = []): string
66
    {
67 12
        $doc = new DOMDocument('1.0');
68 12
        if ([] === $header_record && [] === $footer_record) {
69 3
            $table = $this->xml_converter->import($records, $doc);
70 3
            $this->styleTableElement($table);
71 3
            $doc->appendChild($table);
72
73 3
            return $doc->saveHTML();
74
        }
75
76 9
        $table = $doc->createElement('table');
77 9
        $this->styleTableElement($table);
78 9
        $this->appendTableHeaderSection('thead', $header_record, $table);
79 9
        $this->appendTableHeaderSection('tfoot', $footer_record, $table);
80 9
        $table->appendChild($this->xml_converter->rootElement('tbody')->import($records, $doc));
81 9
        $doc->appendChild($table);
82
83 9
        return $doc->saveHTML();
84
    }
85
86
    /**
87
     * HTML table class name setter.
88
     *
89
     * @throws DOMException if the id_value contains any type of whitespace
90
     */
91 6
    public function table(string $class_name, string $id_value = ''): self
92
    {
93 6
        if (1 === preg_match(",\s,", $id_value)) {
94 3
            throw new DOMException("the id attribute's value must not contain whitespace (spaces, tabs etc.)");
95
        }
96 3
        $clone = clone $this;
97 3
        $clone->class_name = $class_name;
98 3
        $clone->id_value = $id_value;
99
100 3
        return $clone;
101
    }
102
103
    /**
104
     * HTML tr record offset attribute setter.
105
     */
106 3
    public function tr(string $record_offset_attribute_name): self
107
    {
108 3
        $clone = clone $this;
109 3
        $clone->xml_converter = $this->xml_converter->recordElement('tr', $record_offset_attribute_name);
110
111 3
        return $clone;
112
    }
113
114
    /**
115
     * HTML td field name attribute setter.
116
     */
117 3
    public function td(string $fieldname_attribute_name): self
118
    {
119 3
        $clone = clone $this;
120 3
        $clone->xml_converter = $this->xml_converter->fieldElement('td', $fieldname_attribute_name);
121
122 3
        return $clone;
123
    }
124
125
    /**
126
     * Create a DOMElement representing a single record of data.
127
     */
128 9
    private function appendTableHeaderSection(string $node_name, array $record, DOMElement $table)
129
    {
130 9
        if ([] === $record) {
131 6
            return;
132
        }
133
134 9
        $node = $this->xml_converter
135 9
            ->rootElement($node_name)
136 9
            ->recordElement('tr')
137 9
            ->fieldElement('th')
138 9
            ->import([$record], $table->ownerDocument)
139
        ;
140
141
        /** @var DOMElement $element */
142 9
        foreach ($node->getElementsByTagName('th') as $element) {
143 9
            $element->setAttribute('scope', 'col');
144
        }
145
146 9
        $table->appendChild($node);
147 9
    }
148
149
    /**
150
     * Style the table dom element.
151
     */
152 9
    private function styleTableElement(DOMElement $node)
153
    {
154 9
        $node->setAttribute('class', $this->class_name);
155 9
        $node->setAttribute('id', $this->id_value);
156 9
    }
157
}
158