GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 123c77...5e3efe )
by Viktor
06:45
created

HtmlHeadingNormalizer::headingLevels()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 13
rs 9.4285
cc 2
eloc 8
nc 2
nop 1
1
<?php
2
3
namespace Vikpe;
4
5
class HtmlHeadingNormalizer
6
{
7
    public static function demote($html, $numberOfLevels)
8
    {
9
        return self::normalize($html, $numberOfLevels);
10
    }
11
12
    public static function promote($html, $numberOfLevels)
13
    {
14
        return self::normalize($html, -$numberOfLevels);
15
    }
16
17
    public static function min($html, $minLevel)
18
    {
19
        if (!self::containsHeadings($html)) {
20
            return $html;
21
        }
22
23
        $currentMinLevel = min(self::headingLevels($html));
24
        $levelDiff = $minLevel - $currentMinLevel;
25
26
        return self::normalize($html, $levelDiff);
27
    }
28
29
    private static function normalize($html, $numberOfLevels)
30
    {
31
        $normalizationIsRequired = ((abs($numberOfLevels) > 0) && self::containsHeadings($html));
32
33
        if (!$normalizationIsRequired) {
34
            return $html;
35
        }
36
37
        $domDocument = new \DOMDocument();
38
        $domDocument->loadHTML($html);
39
40
        $originalHeadings = self::getHeadings($domDocument);
41
        $normalizedHeadings = self::normalizeHeadings($originalHeadings, $numberOfLevels);
42
        self::replaceHeadings($originalHeadings, $normalizedHeadings);
43
44
        return self::formatResult($domDocument, $html);
45
    }
46
47
    private static function getHeadings(\DOMDocument $domDocument)
48
    {
49
        $tagNames = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6');
50
        $headings = array();
51
52
        foreach ($tagNames as $tagName) {
53
            foreach ($domDocument->getElementsByTagName($tagName) as $heading) {
54
                $headings[] = $heading;
55
            }
56
        }
57
58
        return $headings;
59
    }
60
61
    private static function normalizeHeadings(array $originalHeadings, $numberOfLevels)
62
    {
63
        $normalizedHeadings = array();
64
65
        foreach ($originalHeadings as $heading) {
66
            $currentLevel = self::tagNameToLevel($heading->tagName);
67
            $newLevel = $currentLevel + $numberOfLevels;
68
69
            $normalizedHeadings[] = self::cloneHeading($heading, $newLevel);
70
        }
71
72
        return $normalizedHeadings;
73
    }
74
75
    private static function replaceHeadings(array $needles, array $replacements)
76
    {
77
        foreach ($needles as $i => $needle) {
78
            $needle->parentNode->replaceChild($replacements[$i], $needle);
79
        }
80
    }
81
82
    private static function containsHeadings($html)
83
    {
84
        $headingNeedle = '<h';
85
        $containsHeadings = (false !== stripos($html, $headingNeedle));
86
87
        return $containsHeadings;
88
    }
89
90
    private static function tagNameToLevel($tagName)
91
    {
92
        return substr($tagName, 1);
93
    }
94
95
    private static function levelToTagName($level)
96
    {
97
        return 'h'.$level;
98
    }
99
100
    private static function cloneHeading(\DOMElement $sourceHeading, $newLevel)
101
    {
102
        $tagName = self::levelToTagName($newLevel);
103
104
        $targetHeading = $sourceHeading->parentNode->ownerDocument->createElement($tagName);
105
        self::copyAttributes($sourceHeading, $targetHeading);
106
        self::moveChildNodes($sourceHeading, $targetHeading);
107
108
        return $targetHeading;
109
    }
110
111
    private static function copyAttributes(\DOMElement $source, \DOMElement $target)
112
    {
113
        foreach ($source->attributes as $attribute) {
114
            $target->setAttribute($attribute->name, $attribute->value);
115
        }
116
    }
117
118
    private static function moveChildNodes(\DOMElement $source, \DOMElement $target)
119
    {
120
        while ($source->hasChildNodes()) {
121
            // appendChild() actually moves the childNode
122
            $target->appendChild($source->childNodes->item(0));
123
        }
124
    }
125
126
    private static function formatResult(\DOMDocument $domDocument, $originalHtml)
127
    {
128
        if (!self::containsDocType($originalHtml)) {
129
            $domDocument->removeChild($domDocument->doctype);
130
        }
131
132
        if (self::containsHtmlTag($originalHtml)) {
133
            return $domDocument->saveHTML();
134
        } else {
135
            $bodyDomElement = $domDocument->getElementsByTagName('body')
136
                                          ->item(0);
137
138
            $html = $domDocument->saveHTML($bodyDomElement);
139
140
            return str_replace(array('<body>', '</body>'), '', $html);
141
        }
142
    }
143
144
    private static function containsDocType($html)
145
    {
146
        return self::stringContains($html, '<!DOCTYPE');
147
    }
148
149
    private static function stringContains($string, $needle)
150
    {
151
        return false !== strpos($string, $needle);
152
    }
153
154
    private static function containsHtmlTag($html)
155
    {
156
        return self::stringContains($html, '<html');
157
    }
158
159
    private static function headingLevels($html)
160
    {
161
        $domDocument = new \DOMDocument();
162
        $domDocument->loadHTML($html);
163
        $headings = self::getHeadings($domDocument);
164
        $headingLevels = array();
165
166
        foreach ($headings as $heading) {
167
            $headingLevels[] = self::tagNameToLevel($heading->tagName);
168
        }
169
170
        return $headingLevels;
171
    }
172
}
173