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 ( 886ade...958e6d )
by Viktor
05:50
created

HtmlHeadingNormalizer   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 147
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 26
c 3
b 0
f 0
lcom 1
cbo 0
dl 0
loc 147
rs 10

16 Methods

Rating   Name   Duplication   Size   Complexity  
A demote() 0 4 1
A promote() 0 4 1
A normalizeHeadings() 0 13 2
A replaceHeadings() 0 6 2
A containsHeadings() 0 7 1
A tagNameToLevel() 0 4 1
A levelToTagName() 0 4 1
A normalize() 0 22 3
A getHeadings() 0 13 3
A cloneHeading() 0 10 1
A copyAttributes() 0 6 2
A moveChildNodes() 0 7 2
A formatResult() 0 17 3
A containsDocType() 0 4 1
A stringContains() 0 4 1
A containsHtmlTag() 0 4 1
1
<?php
2
3
namespace Vikpe;
4
5
class HtmlHeadingNormalizer
6
{
7
    public static function demote($html, $levels)
8
    {
9
        return self::normalize($html, $levels);
10
    }
11
12
    public static function promote($html, $levels)
13
    {
14
        return self::normalize($html, -$levels);
15
    }
16
17
    private static function normalize($html, $levels)
18
    {
19
        $normalizationIsRequired = ((abs($levels) > 0) && self::containsHeadings($html));
20
21
        if (!$normalizationIsRequired) {
22
            return $html;
23
        }
24
25
        $domDocument = new \DOMDocument();
26
        $domDocument->loadHTML($html);
27
28
        $originalHeadings = self::getHeadings($domDocument);
29
        $normalizedHeadings = self::normalizeHeadings($originalHeadings, $levels);
30
31
        self::replaceHeadings(
32
            $originalHeadings,
33
            $normalizedHeadings
34
        );
35
36
        return $domDocument->saveHTML();
37
        return self::formatResult($domDocument, $html);
0 ignored issues
show
Unused Code introduced by
return self::formatResult($domDocument, $html); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
38
    }
39
40
    private static function getHeadings(\DOMDocument $domDocument)
41
    {
42
        $tagNames = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6');
43
        $headings = array();
44
45
        foreach ($tagNames as $tagName) {
46
            foreach ($domDocument->getElementsByTagName($tagName) as $heading) {
47
                $headings[] = $heading;
48
            }
49
        }
50
51
        return $headings;
52
    }
53
54
    private static function normalizeHeadings(array $originalHeadings, $levelDelta)
55
    {
56
        $normalizedHeadings = array();
57
58
        foreach ($originalHeadings as $heading) {
59
            $currentLevel = self::tagNameToLevel($heading->tagName);
60
            $newLevel = $currentLevel + $levelDelta;
61
62
            $normalizedHeadings[] = self::cloneHeading($heading, $newLevel);
63
        }
64
65
        return $normalizedHeadings;
66
    }
67
68
    private static function replaceHeadings(array $needles, array $replacements)
69
    {
70
        foreach ($needles as $i => $needle) {
71
            $needle->parentNode->replaceChild($replacements[$i], $needle);
72
        }
73
    }
74
75
    private static function containsHeadings($html)
76
    {
77
        $headingNeedle = '<h';
78
        $containsHeadings = (false !== stripos($html, $headingNeedle));
79
80
        return $containsHeadings;
81
    }
82
83
    private static function tagNameToLevel($tagName)
84
    {
85
        return substr($tagName, 1);
86
    }
87
88
    private static function levelToTagName($level)
89
    {
90
        return 'h'.$level;
91
    }
92
93
    private static function cloneHeading(\DOMElement $sourceHeading, $newLevel)
94
    {
95
        $tagName = self::levelToTagName($newLevel);
96
97
        $targetHeading = $sourceHeading->parentNode->ownerDocument->createElement($tagName);
98
        self::copyAttributes($sourceHeading, $targetHeading);
99
        self::moveChildNodes($sourceHeading, $targetHeading);
100
101
        return $targetHeading;
102
    }
103
104
    private static function copyAttributes(\DOMElement $source, \DOMElement $target)
105
    {
106
        foreach ($source->attributes as $attribute) {
107
            $target->setAttribute($attribute->name, $attribute->value);
108
        }
109
    }
110
111
    private static function moveChildNodes(\DOMElement $source, \DOMElement $target)
112
    {
113
        while ($source->hasChildNodes()) {
114
            // appendChild() actually moves the childNode
115
            $target->appendChild($source->childNodes->item(0));
116
        }
117
    }
118
119
    private static function formatResult(\DOMDocument $domDocument, $originalHtml)
120
    {
121
        if (!self::containsDocType($originalHtml)) {
122
            $domDocument->removeChild($domDocument->doctype);
123
        }
124
125
        if (self::containsHtmlTag($originalHtml)) {
126
            return $domDocument->saveHTML();
127
        } else {
128
            $bodyDomElement = $domDocument->getElementsByTagName('body')
129
                                          ->item(0);
130
131
            $html = $domDocument->saveHTML($bodyDomElement);
132
133
            return str_replace(['<body>', '</body>'], '', $html);
134
        }
135
    }
136
137
    private static function containsDocType($html)
138
    {
139
        return self::stringContains($html, '<!DOCTYPE');
140
    }
141
142
    private static function stringContains($string, $needle)
143
    {
144
        return (false !== strpos($string, $needle));
145
    }
146
147
    private static function containsHtmlTag($html)
148
    {
149
        return self::stringContains($html, '<html');
150
    }
151
}
152