Completed
Push — master ( 30aab1...cadcfa )
by Asmir
07:00
created

TreeBuildingRules   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Coupling/Cohesion

Dependencies 0

Test Coverage

Coverage 84.21%

Importance

Changes 0
Metric Value
wmc 22
cbo 0
dl 0
loc 124
ccs 48
cts 57
cp 0.8421
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A hasRules() 0 4 1
C evaluate() 0 43 15
A handleLI() 0 6 1
A handleDT() 0 7 1
A handleRT() 0 7 1
A closeIfCurrentMatches() 0 10 2
1
<?php
2
namespace Masterminds\HTML5\Parser;
3
4
/**
5
 * Handles special-case rules for the DOM tree builder.
6
 *
7
 * Many tags have special rules that need to be accomodated on an
8
 * individual basis. This class handles those rules.
9
 *
10
 * See section 8.1.2.4 of the spec.
11
 *
12
 * @todo - colgroup and col special behaviors
13
 *       - body and head special behaviors
14
 */
15
class TreeBuildingRules
16
{
17
18
    protected static $tags = array(
19
        'li' => 1,
20
        'dd' => 1,
21
        'dt' => 1,
22
        'rt' => 1,
23
        'rp' => 1,
24
        'tr' => 1,
25
        'th' => 1,
26
        'td' => 1,
27
        'thead' => 1,
28
        'tfoot' => 1,
29
        'tbody' => 1,
30
        'table' => 1,
31
        'optgroup' => 1,
32
        'option' => 1
33
    );
34
35
    /**
36
     * Build a new rules engine.
37
     *
38
     * @param \DOMDocument $doc
39
     *            The DOM document to use for evaluation and modification.
40
     */
41 111
    public function __construct($doc)
42
    {
43 111
        $this->doc = $doc;
44 111
    }
45
46
    /**
47
     * Returns true if the given tagname has special processing rules.
48
     */
49 107
    public function hasRules($tagname)
50
    {
51 107
        return isset(static::$tags[$tagname]);
52
    }
53
54
    /**
55
     * Evaluate the rule for the current tag name.
56
     *
57
     * This may modify the existing DOM.
58
     *
59
     * @return \DOMElement The new Current DOM element.
60
     */
61 6
    public function evaluate($new, $current)
62
    {
63 6
        switch ($new->tagName) {
64 6
            case 'li':
65 2
                return $this->handleLI($new, $current);
66 4
            case 'dt':
67 4
            case 'dd':
68 1
                return $this->handleDT($new, $current);
69 3
            case 'rt':
70 3
            case 'rp':
71
                return $this->handleRT($new, $current);
72 3
            case 'optgroup':
73 2
                return $this->closeIfCurrentMatches($new, $current, array(
74
                    'optgroup'
75 2
                ));
76 3
            case 'option':
77 2
                return $this->closeIfCurrentMatches($new, $current, array(
78 2
                    'option',
79 2
                ));
80 1
            case 'tr':
81
                return $this->closeIfCurrentMatches($new, $current, array(
82
                    'tr'
83
                ));
84 1
            case 'td':
85 1
            case 'th':
86 1
                return $this->closeIfCurrentMatches($new, $current, array(
87 1
                    'th',
88
                    'td'
89 1
                ));
90 1
            case 'tbody':
91 1
            case 'thead':
92 1
            case 'tfoot':
93 1
            case 'table': // Spec isn't explicit about this, but it's necessary.
94
95 1
                return $this->closeIfCurrentMatches($new, $current, array(
96 1
                    'thead',
97 1
                    'tfoot',
98
                    'tbody'
99 1
                ));
100
        }
101
102
        return $current;
103
    }
104
105 2
    protected function handleLI($ele, $current)
106
    {
107 2
        return $this->closeIfCurrentMatches($ele, $current, array(
108
            'li'
109 2
        ));
110
    }
111
112 1
    protected function handleDT($ele, $current)
113
    {
114 1
        return $this->closeIfCurrentMatches($ele, $current, array(
115 1
            'dt',
116
            'dd'
117 1
        ));
118
    }
119
120
    protected function handleRT($ele, $current)
121
    {
122
        return $this->closeIfCurrentMatches($ele, $current, array(
123
            'rt',
124
            'rp'
125
        ));
126
    }
127
128 6
    protected function closeIfCurrentMatches($ele, $current, $match)
129
    {
130 6
        if (in_array($current->tagName, $match)) {
131 4
            $current->parentNode->appendChild($ele);
132 4
        } else {
133 6
            $current->appendChild($ele);
134
        }
135
136 6
        return $ele;
137
    }
138
}
139