HTMLTable   A
last analyzed

Complexity

Total Complexity 24

Size/Duplication

Total Lines 204
Duplicated Lines 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
wmc 24
eloc 71
c 3
b 1
f 0
dl 0
loc 204
rs 10

12 Methods

Rating   Name   Duplication   Size   Complexity  
A resolveTag() 0 9 3
A render() 0 53 5
A getIndentation() 0 3 1
A resolveLeftType() 0 13 3
A setIndentation() 0 5 1
A getNewlineCharacter() 0 3 1
A getCellContent() 0 20 3
A getTab() 0 3 1
A getSeparator() 0 3 1
A setTab() 0 5 1
A resolveRightType() 0 13 3
A setSeparator() 0 5 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Mistrals\Diff\Renderer;
6
7
use Mistralys\Diff\Diff;
8
use Mistralys\Diff\DiffException;
9
10
class HTMLTable extends Renderer
11
{
12
    private string $separator = '<br>';
13
    private string $indentation = '';
14
    private string $tab = '    ';
15
    private string $nl = PHP_EOL;
16
    private string $container = '<table class="text-diff-container">%s</table>';
17
18
   /**
19
    * @var array<int, array<int,int|string>>
20
    */
21
    private $array;
22
23
   /**
24
    * Sets the tab character(s) to indent the HTML code with.
25
    * This is used to indent the table's tags beyond the
26
    * base indentation.
27
    * 
28
    * @param string $tab
29
    * @return HTMLTable
30
    * @see HTMLTable::setIndentation()
31
    */
32
    public function setTab(string $tab) : HTMLTable
33
    {
34
        $this->tab = $tab;
35
        
36
        return $this;
37
    }
38
    
39
    public function getTab() : string
40
    {
41
        return $this->tab;
42
    }
43
    
44
    public function getNewlineCharacter() : string
45
    {
46
        return $this->nl;
47
    }
48
    
49
   /**
50
    * Sets the character
51
    * @param string $separator
52
    * @return HTMLTable
53
    */
54
    public function setSeparator(string $separator) : HTMLTable
55
    {
56
        $this->separator = $separator;
57
        
58
        return $this;
59
    }
60
    
61
   /**
62
    * Sets the character(s) to indent the whole table with.
63
    *  
64
    * @param string $indent
65
    * @return HTMLTable
66
    * @see HTMLTable::setTab()
67
    */
68
    public function setIndentation(string $indent) : HTMLTable
69
    {
70
        $this->indentation = $indent;
71
        
72
        return $this;
73
    }
74
    
75
    public function getSeparator() : string
76
    {
77
        return $this->separator;
78
    }
79
    
80
    public function getIndentation() : string
81
    {
82
        return $this->indentation;
83
    }
84
85
    /**
86
     * Returns a diff as an HTML table.
87
     *
88
     * @return string
89
     * @throws DiffException
90
     */
91
    public function render() : string
92
    {
93
        $this->array = $this->diff->toArray();
94
95
        $i1 = $this->indentation;
96
        $i2 = $this->indentation.$this->tab;
97
        $i3 = $this->indentation.$this->tab.$this->tab;
98
        $nl = PHP_EOL;
99
        
100
        $html = '';
101
        
102
        // loop over the lines in the diff
103
        $index = 0;
104
        while ($index < count($this->array))
105
        {
106
            $leftCell = '';
107
            $rightCell = '';
108
            
109
            // determine the line type
110
            switch ($this->array[$index][1])
111
            {
112
                // display the content on the left and right
113
                case Diff::UNMODIFIED:
114
                    $leftCell = $this->getCellContent($index, Diff::UNMODIFIED);
115
                    $rightCell = $leftCell;
116
                    break;
117
                    
118
                    // display the deleted on the left and inserted content on the right
119
                case Diff::DELETED:
120
                    $leftCell = $this->getCellContent($index, Diff::DELETED);
121
                    $rightCell = $this->getCellContent($index, Diff::INSERTED);
122
                    break;
123
                    
124
                    // display the inserted content on the right
125
                case Diff::INSERTED:
126
                    $rightCell = $this->getCellContent($index, Diff::INSERTED);
127
                    break;
128
                    
129
            }
130
            
131
            $leftType = $this->resolveLeftType($leftCell, $rightCell);
132
            $rightType = $this->resolveRightType($leftCell, $rightCell);
133
            
134
            // extend the HTML with the new row
135
            $html .=
136
            $i2. "<tr>". $nl . 
137
            $i3.     '<td class="text-diff-'.$leftType. '">'. $leftCell . "</td>".$nl.
138
            $i3.     '<td class="text-diff-'.$rightType. '">'. $rightCell . "</td>".$nl.
139
            $i2. "</tr>".$nl;
140
                                                
141
        }
142
        
143
        return $i1. sprintf($this->container, $nl.$html).$nl;
144
    }
145
    
146
    private function resolveLeftType(string $leftCell, string $rightCell) : string
147
    {
148
        if(empty($leftCell))
149
        {
150
            return 'empty';
151
        }
152
        
153
        if($leftCell !== $rightCell)
154
        {
155
            return 'del';
156
        }
157
        
158
        return 'unmodified';
159
    }
160
    
161
    private function resolveRightType(string $leftCell, string $rightCell) : string
162
    {
163
        if(empty($rightCell))
164
        {
165
            return 'empty';
166
        }
167
        
168
        if($leftCell !== $rightCell)
169
        {
170
            return 'ins';
171
        }
172
        
173
        return 'unmodified';
174
    }
175
    
176
   /**
177
    * Returns the content of the cell.
178
    * 
179
    * @param int $index
180
    * @param int $type The operation type (inset/delete/unmodified)
181
    * @return string
182
    */
183
    private function getCellContent(int &$index, int $type) : string
184
    {
185
        // initialise the HTML
186
        $html = '';
187
        $tag = $this->resolveTag($type);
188
        
189
        // loop over the matching lines, adding them to the HTML
190
        while ($index < count($this->array) && $this->array[$index][1] === $type)
191
        {
192
            $html .= sprintf(
193
                '<%1$s>%2$s</%1$s>%3$s',
194
                $tag,
195
                htmlspecialchars((string)$this->array[$index][0]),
196
                $this->separator
197
            );
198
            
199
            $index ++;
200
        }
201
        
202
        return $html;
203
    }
204
    
205
    private function resolveTag(int $type) : string
206
    {
207
        switch($type)
208
        {
209
            case Diff::DELETED: return 'del';
210
            case Diff::INSERTED: return 'ins';
211
        }
212
        
213
        return 'span';
214
    }
215
}
216