PluginHtmlFormat   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 160
Duplicated Lines 13.75 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 22
loc 160
rs 10
c 0
b 0
f 0
wmc 23
lcom 1
cbo 1

5 Methods

Rating   Name   Duplication   Size   Complexity  
A process() 0 12 1
B tagDispatcher() 0 18 11
A openTag() 8 23 4
A closeTag() 7 19 3
A singleTag() 7 24 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * Copyright (c) 2013-2016
4
 *
5
 * @category  Library
6
 * @package   Dwoo\Plugins\Filters
7
 * @author    Jordi Boggiano <[email protected]>
8
 * @author    David Sanchez <[email protected]>
9
 * @copyright 2008-2013 Jordi Boggiano
10
 * @copyright 2013-2016 David Sanchez
11
 * @license   http://dwoo.org/LICENSE Modified BSD License
12
 * @version   1.3.0
13
 * @date      2016-09-18
14
 * @link      http://dwoo.org/
15
 */
16
17
namespace Dwoo\Plugins\Filters;
18
19
use Dwoo\Filter;
20
21
/**
22
 * Formats any html output (must be valid xml where every tag opened is closed)
23
 * using a single tab for indenting. 'pre' and other whitespace sensitive
24
 * tags should not be affected.
25
 * It is not recommended to use this on every template if you render multiple
26
 * templates per page, you should only use it once on the main page template so that
27
 * everything is formatted in one pass.
28
 * This software is provided 'as-is', without any express or implied warranty.
29
 * In no event will the authors be held liable for any damages arising from the use of this software.
30
 */
31
class PluginHtmlFormat extends Filter
32
{
33
    /**
34
     * tab count to auto-indent the source.
35
     *
36
     * @var int
37
     */
38
    protected static $tabCount = - 1;
39
40
    /**
41
     * stores the additional data (following a tag) of the last call to open/close/singleTag.
42
     *
43
     * @var string
44
     */
45
    protected static $lastCallAdd = '';
46
47
    /**
48
     * formats the input using the singleTag/closeTag/openTag functions.
49
     * It is auto indenting the whole code, excluding <textarea>, <code> and <pre> tags that must be kept intact.
50
     * Those tags must however contain only htmlentities-escaped text for everything to work properly.
51
     * Inline tags are presented on a single line with their content
52
     *
53
     * @param string $input the xhtml to format
54
     *
55
     * @return string formatted xhtml
56
     */
57
    public function process($input)
58
    {
59
        self::$tabCount = - 1;
60
61
        // auto indent all but textareas & pre (or we have weird tabs inside)
62
        $input = preg_replace_callback("#(<[^>]+>)(\s*)([^<]*)#", array(
63
            'self',
64
            'tagDispatcher'
65
        ), $input);
66
67
        return $input;
68
    }
69
70
    /**
71
     * helper function for format()'s preg_replace call.
72
     *
73
     * @param array $input array of matches (1=>tag, 2=>whitespace(optional), 3=>additional non-html content)
74
     *
75
     * @return string the indented tag
76
     */
77
    protected static function tagDispatcher($input)
78
    {
79
        // textarea, pre, code tags and comments are to be left alone to avoid any non-wanted whitespace inside them so it just outputs them as they were
80
        if (substr($input[1], 0, 9) == '<textarea' || substr($input[1], 0, 4) == '<pre' || substr($input[1], 0, 5) == '<code' || substr($input[1], 0, 4) == '<!--' || substr($input[1], 0, 9) == '<![CDATA[') {
81
            return $input[1] . $input[3];
82
        }
83
        // closing textarea, code and pre tags and self-closed tags (i.e. <br />) are printed as singleTags because we didn't use openTag for the formers and the latter is a single tag
84
        if (substr($input[1], 0, 10) == '</textarea' || substr($input[1], 0, 5) == '</pre' || substr($input[1], 0, 6) == '</code' || substr($input[1], - 2) == '/>') {
85
            return self::singleTag($input[1], $input[3], $input[2]);
86
        }
87
        // it's the closing tag
88
        if ($input[0][1] == '/') {
89
            return self::closeTag($input[1], $input[3], $input[2]);
90
        }
91
92
        // opening tag
93
        return self::openTag($input[1], $input[3], $input[2]);
94
    }
95
96
    /**
97
     * returns an open tag and adds a tab into the auto indenting.
98
     *
99
     * @param string $tag        content of the tag
100
     * @param string $add        additional data (anything before the following tag)
101
     * @param string $whitespace white space between the tag and the additional data
102
     *
103
     * @return string
104
     */
105
    protected static function openTag($tag, $add, $whitespace)
106
    {
107
        $tabs = str_pad('', self::$tabCount ++, "\t");
108
109
        if (preg_match('#^<(a|label|option|textarea|h1|h2|h3|h4|h5|h6|strong|b|em|i|abbr|acronym|cite|span|sub|sup|u|s|title)(?: [^>]*|)>#', $tag)) {
110
            // if it's one of those tag it's inline so it does not require a leading line break
111
            $result = $tag . $whitespace . str_replace("\n", "\n" . $tabs, $add);
112
        } elseif (substr($tag, 0, 9) == '<!DOCTYPE') {
113
            // it's the doctype declaration so no line break here either
114
            $result = $tabs . $tag;
115 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
116
            // normal block tag
117
            $result = "\n" . $tabs . $tag;
118
119
            if (!empty($add)) {
120
                $result .= "\n" . $tabs . "\t" . str_replace("\n", "\n\t" . $tabs, $add);
121
            }
122
        }
123
124
        self::$lastCallAdd = $add;
125
126
        return $result;
127
    }
128
129
    /**
130
     * returns a closing tag and removes a tab from the auto indenting.
131
     *
132
     * @param string $tag        content of the tag
133
     * @param string $add        additional data (anything before the following tag)
134
     * @param string $whitespace white space between the tag and the additional data
135
     *
136
     * @return string
137
     */
138
    protected static function closeTag($tag, $add, $whitespace)
139
    {
140
        $tabs = str_pad('', -- self::$tabCount, "\t");
141
142
        // if it's one of those tag it's inline so it does not require a leading line break
143
        if (preg_match('#^</(a|label|option|textarea|h1|h2|h3|h4|h5|h6|strong|b|em|i|abbr|acronym|cite|span|sub|sup|u|s|title)>#', $tag)) {
144
            $result = $tag . $whitespace . str_replace("\n", "\n" . $tabs, $add);
145 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
146
            $result = "\n" . $tabs . $tag;
147
148
            if (!empty($add)) {
149
                $result .= "\n" . $tabs . "\t" . str_replace("\n", "\n\t" . $tabs, $add);
150
            }
151
        }
152
153
        self::$lastCallAdd = $add;
154
155
        return $result;
156
    }
157
158
    /**
159
     * returns a single tag with auto indenting.
160
     *
161
     * @param string $tag content of the tag
162
     * @param string $add additional data (anything before the following tag)
163
     *
164
     * @return string
165
     */
166
    protected static function singleTag($tag, $add, $whitespace)
167
    {
168
        $tabs = str_pad('', self::$tabCount, "\t");
169
170
        // if it's img, br it's inline so it does not require a leading line break
171
        // if it's a closing textarea, code or pre tag, it does not require a leading line break either or it creates whitespace at the end of those blocks
172
        if (preg_match('#^<(img|br|/textarea|/pre|/code)(?: [^>]*|)>#', $tag)) {
173
            $result = $tag . $whitespace;
174
175
            if (!empty($add)) {
176
                $result .= str_replace("\n", "\n" . $tabs, $add);
177
            }
178 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
179
            $result = "\n" . $tabs . $tag;
180
181
            if (!empty($add)) {
182
                $result .= "\n" . $tabs . str_replace("\n", "\n" . $tabs, $add);
183
            }
184
        }
185
186
        self::$lastCallAdd = $add;
187
188
        return $result;
189
    }
190
}
191