html_Core   F
last analyzed

Complexity

Total Complexity 63

Size/Duplication

Total Lines 395
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 1

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 395
rs 3.6585
wmc 63
lcom 0
cbo 1

15 Methods

Rating   Name   Duplication   Size   Complexity  
A specialchars() 0 21 3
A specialurlencode() 0 4 1
D anchor() 0 25 10
A file_anchor() 0 10 3
A panchor() 0 4 1
A anchor_array() 0 9 2
B email() 0 16 6
B mailto() 0 30 5
A breadcrumb() 0 17 3
A meta() 0 18 4
A stylesheet() 0 4 1
D link() 0 41 10
B script() 0 24 5
B image() 0 19 5
A attributes() 0 17 4

How to fix   Complexity   

Complex Class

Complex classes like html_Core often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use html_Core, and based on these observations, apply Extract Interface, too.

1
<?php defined('SYSPATH') or die('No direct access allowed.');
2
/**
3
 * HTML helper class.
4
 *
5
 * $Id: html.php 4376 2009-06-01 11:40:39Z samsoir $
6
 *
7
 * @package    Core
8
 * @author     Kohana Team
9
 * @copyright  (c) 2007-2008 Kohana Team
10
 * @license    http://kohanaphp.com/license.html
11
 */
12
class html_Core
13
{
14
15
    // Enable or disable automatic setting of target="_blank"
16
    public static $windowed_urls = false;
17
18
    /**
19
     * Convert special characters to HTML entities
20
     *
21
     * @param   string   string to convert
22
     * @param   boolean  encode existing entities
23
     * @return  string
24
     */
25
    public static function specialchars($str, $double_encode = true)
26
    {
27
        // Force the string to be a string
28
        $str = (string) $str;
29
30
        // Do encode existing HTML entities (default)
31
        if ($double_encode === true) {
32
            $str = htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
33
        } else {
34
            // Do not encode existing HTML entities
35
            // From PHP 5.2.3 this functionality is built-in, otherwise use a regex
36
            if (version_compare(PHP_VERSION, '5.2.3', '>=')) {
37
                $str = htmlspecialchars($str, ENT_QUOTES, 'UTF-8', false);
38
            } else {
39
                $str = preg_replace('/&(?!(?:#\d++|[a-z]++);)/ui', '&amp;', $str);
40
                $str = str_replace(array('<', '>', '\'', '"'), array('&lt;', '&gt;', '&#39;', '&quot;'), $str);
41
            }
42
        }
43
44
        return $str;
45
    }
46
47
    /**
48
     * Perform a html::specialchars() with additional URL specific encoding.
49
     *
50
     * @param   string   string to convert
51
     * @param   boolean  encode existing entities
52
     * @return  string
53
     */
54
    public static function specialurlencode($str, $double_encode = true)
55
    {
56
        return str_replace(' ', '%20', html::specialchars($str, $double_encode));
57
    }
58
    
59
    /**
60
     * Create HTML link anchors.
61
     *
62
     * @param   string  URL or URI string
63
     * @param   string  link text
64
     * @param   array   HTML anchor attributes
65
     * @param   string  non-default protocol, eg: https
66
     * @param   boolean option to escape the title that is output
67
     * @return  string
68
     */
69
    public static function anchor($uri, $title = null, $attributes = null, $protocol = null, $escape_title = false)
70
    {
71
        if ($uri === '') {
72
            $site_url = url::base(false);
73
        } elseif (strpos($uri, '#') === 0) {
74
            // This is an id target link, not a URL
75
            $site_url = $uri;
76
        } elseif (strpos($uri, '://') === false) {
77
            $site_url = url::site($uri, $protocol);
78
        } else {
79
            if (html::$windowed_urls === true and empty($attributes['target'])) {
80
                $attributes['target'] = '_blank';
81
            }
82
83
            $site_url = $uri;
84
        }
85
86
        return
87
        // Parsed URL
88
        '<a href="'.html::specialurlencode($site_url, false).'"'
89
        // Attributes empty? Use an empty string
90
        .(is_array($attributes) ? html::attributes($attributes) : '').'>'
91
        // Title empty? Use the parsed URL
92
        .($escape_title ? html::specialchars((($title === null) ? $site_url : $title), false) : (($title === null) ? $site_url : $title)).'</a>';
93
    }
94
95
    /**
96
     * Creates an HTML anchor to a file.
97
     *
98
     * @param   string  name of file to link to
99
     * @param   string  link text
100
     * @param   array   HTML anchor attributes
101
     * @param   string  non-default protocol, eg: ftp
102
     * @return  string
103
     */
104
    public static function file_anchor($file, $title = null, $attributes = null, $protocol = null)
105
    {
106
        return
107
        // Base URL + URI = full URL
108
        '<a href="'.html::specialurlencode(url::base(false, $protocol).$file, false).'"'
109
        // Attributes empty? Use an empty string
110
        .(is_array($attributes) ? html::attributes($attributes) : '').'>'
111
        // Title empty? Use the filename part of the URI
112
        .(($title === null) ? end(explode('/', $file)) : $title) .'</a>';
0 ignored issues
show
Bug introduced by
explode('/', $file) cannot be passed to end() as the parameter $array expects a reference.
Loading history...
113
    }
114
115
    /**
116
     * Similar to anchor, but with the protocol parameter first.
117
     *
118
     * @param   string  link protocol
119
     * @param   string  URI or URL to link to
120
     * @param   string  link text
121
     * @param   array   HTML anchor attributes
122
     * @return  string
123
     */
124
    public static function panchor($protocol, $uri, $title = null, $attributes = false)
125
    {
126
        return html::anchor($uri, $title, $attributes, $protocol);
127
    }
128
129
    /**
130
     * Create an array of anchors from an array of link/title pairs.
131
     *
132
     * @param   array  link/title pairs
133
     * @return  array
134
     */
135
    public static function anchor_array(array $array)
136
    {
137
        $anchors = array();
138
        foreach ($array as $link => $title) {
139
            // Create list of anchors
140
            $anchors[] = html::anchor($link, $title);
141
        }
142
        return $anchors;
143
    }
144
145
    /**
146
     * Generates an obfuscated version of an email address.
147
     *
148
     * @param   string  email address
149
     * @return  string
150
     */
151
    public static function email($email)
152
    {
153
        $safe = '';
154
        foreach (str_split($email) as $letter) {
155
            switch (($letter === '@') ? rand(1, 2) : rand(1, 3)) {
156
                // HTML entity code
157
                case 1: $safe .= '&#'.ord($letter).';'; break;
158
                // Hex character code
159
                case 2: $safe .= '&#x'.dechex(ord($letter)).';'; break;
160
                // Raw (no) encoding
161
                case 3: $safe .= $letter;
162
            }
163
        }
164
165
        return $safe;
166
    }
167
168
    /**
169
     * Creates an email anchor.
170
     *
171
     * @param   string  email address to send to
172
     * @param   string  link text
173
     * @param   array   HTML anchor attributes
174
     * @return  string
175
     */
176
    public static function mailto($email, $title = null, $attributes = null)
177
    {
178
        if (empty($email)) {
179
            return $title;
180
        }
181
182
        // Remove the subject or other parameters that do not need to be encoded
183
        if (strpos($email, '?') !== false) {
184
            // Extract the parameters from the email address
185
            list($email, $params) = explode('?', $email, 2);
186
187
            // Make the params into a query string, replacing spaces
188
            $params = '?'.str_replace(' ', '%20', $params);
189
        } else {
190
            // No parameters
191
            $params = '';
192
        }
193
194
        // Obfuscate email address
195
        $safe = html::email($email);
196
197
        // Title defaults to the encoded email address
198
        empty($title) and $title = $safe;
199
200
        // Parse attributes
201
        empty($attributes) or $attributes = html::attributes($attributes);
202
203
        // Encoded start of the href="" is a static encoded version of 'mailto:'
204
        return '<a href="&#109;&#097;&#105;&#108;&#116;&#111;&#058;'.$safe.$params.'"'.$attributes.'>'.$title.'</a>';
205
    }
206
207
    /**
208
     * Generate a "breadcrumb" list of anchors representing the URI.
209
     *
210
     * @param   array   segments to use as breadcrumbs, defaults to using Router::$segments
211
     * @return  string
0 ignored issues
show
Documentation introduced by
Should the return type not be array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
212
     */
213
    public static function breadcrumb($segments = null)
214
    {
215
        empty($segments) and $segments = Router::$segments;
216
217
        $array = array();
218
        while ($segment = array_pop($segments)) {
219
            $array[] = html::anchor(
220
                // Complete URI for the URL
221
                implode('/', $segments).'/'.$segment,
222
                // Title for the current segment
223
                ucwords(inflector::humanize($segment))
224
            );
225
        }
226
227
        // Retrun the array of all the segments
228
        return array_reverse($array);
229
    }
230
231
    /**
232
     * Creates a meta tag.
233
     *
234
     * @param   string|array   tag name, or an array of tags
235
     * @param   string         tag "content" value
236
     * @return  string
237
     */
238
    public static function meta($tag, $value = null)
239
    {
240
        if (is_array($tag)) {
241
            $tags = array();
242
            foreach ($tag as $t => $v) {
243
                // Build each tag and add it to the array
244
                $tags[] = html::meta($t, $v);
245
            }
246
247
            // Return all of the tags as a string
248
            return implode("\n", $tags);
249
        }
250
251
        // Set the meta attribute value
252
        $attr = in_array(strtolower($tag), Kohana::config('http.meta_equiv')) ? 'http-equiv' : 'name';
253
254
        return '<meta '.$attr.'="'.$tag.'" content="'.$value.'" />';
255
    }
256
257
    /**
258
     * Creates a stylesheet link.
259
     *
260
     * @param   string|array  filename, or array of filenames to match to array of medias
261
     * @param   string|array  media type of stylesheet, or array to match filenames
262
     * @param   boolean       include the index_page in the link
263
     * @return  string
264
     */
265
    public static function stylesheet($style, $media = false, $index = false)
266
    {
267
        return html::link($style, 'stylesheet', 'text/css', '.css', $media, $index);
268
    }
269
270
    /**
271
     * Creates a link tag.
272
     *
273
     * @param   string|array  filename
274
     * @param   string|array  relationship
275
     * @param   string|array  mimetype
276
     * @param   string        specifies suffix of the file
277
     * @param   string|array  specifies on what device the document will be displayed
278
     * @param   boolean       include the index_page in the link
279
     * @return  string
280
     */
281
    public static function link($href, $rel, $type, $suffix = false, $media = false, $index = false)
282
    {
283
        $compiled = '';
284
285
        if (is_array($href)) {
286
            foreach ($href as $_href) {
287
                $_rel   = is_array($rel) ? array_shift($rel) : $rel;
288
                $_type  = is_array($type) ? array_shift($type) : $type;
289
                $_media = is_array($media) ? array_shift($media) : $media;
290
291
                $compiled .= html::link($_href, $_rel, $_type, $suffix, $_media, $index);
292
            }
293
        } else {
294
            if (strpos($href, '://') === false) {
295
                // Make the URL absolute
296
                $href = url::base($index).$href;
297
            }
298
299
            $length = strlen($suffix);
300
301
            if ($length > 0 and substr_compare($href, $suffix, -$length, $length, false) !== 0) {
302
                // Add the defined suffix
303
                $href .= $suffix;
304
            }
305
306
            $attr = array(
307
                'rel' => $rel,
308
                'type' => $type,
309
                'href' => $href,
310
            );
311
312
            if (! empty($media)) {
313
                // Add the media type to the attributes
314
                $attr['media'] = $media;
315
            }
316
317
            $compiled = '<link'.html::attributes($attr).' />';
318
        }
319
320
        return $compiled."\n";
321
    }
322
323
    /**
324
     * Creates a script link.
325
     *
326
     * @param   string|array  filename
327
     * @param   boolean       include the index_page in the link
328
     * @return  string
329
     */
330
    public static function script($script, $index = false)
331
    {
332
        $compiled = '';
333
334
        if (is_array($script)) {
335
            foreach ($script as $name) {
336
                $compiled .= html::script($name, $index);
337
            }
338
        } else {
339
            if (strpos($script, '://') === false) {
340
                // Add the suffix only when it's not already present
341
                $script = url::base((bool) $index).$script;
342
            }
343
344
            if (substr_compare($script, '.js', -3, 3, false) !== 0) {
345
                // Add the javascript suffix
346
                $script .= '.js';
347
            }
348
349
            $compiled = '<script type="text/javascript" src="'.$script.'"></script>';
350
        }
351
352
        return $compiled."\n";
353
    }
354
355
    /**
356
     * Creates a image link.
357
     *
358
     * @param   string        image source, or an array of attributes
359
     * @param   string|array  image alt attribute, or an array of attributes
360
     * @param   boolean       include the index_page in the link
361
     * @return  string
362
     */
363
    public static function image($src = null, $alt = null, $index = false)
364
    {
365
        // Create attribute list
366
        $attributes = is_array($src) ? $src : array('src' => $src);
367
368
        if (is_array($alt)) {
369
            $attributes += $alt;
370
        } elseif (! empty($alt)) {
371
            // Add alt to attributes
372
            $attributes['alt'] = $alt;
373
        }
374
375
        if (strpos($attributes['src'], '://') === false) {
376
            // Make the src attribute into an absolute URL
377
            $attributes['src'] = url::base($index).$attributes['src'];
378
        }
379
380
        return '<img'.html::attributes($attributes).' />';
381
    }
382
383
    /**
384
     * Compiles an array of HTML attributes into an attribute string.
385
     *
386
     * @param   string|array  array of attributes
387
     * @return  string
388
     */
389
    public static function attributes($attrs)
390
    {
391
        if (empty($attrs)) {
392
            return '';
393
        }
394
395
        if (is_string($attrs)) {
396
            return ' '.$attrs;
397
        }
398
399
        $compiled = '';
400
        foreach ($attrs as $key => $val) {
401
            $compiled .= ' '.$key.'="'.html::specialchars($val).'"';
402
        }
403
404
        return $compiled;
405
    }
406
} // End html
407