Skip to content

Commit 8cd4001

Browse files
committed
Initial release
1 parent d4f2844 commit 8cd4001

File tree

4 files changed

+435
-0
lines changed

4 files changed

+435
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# v1.0.0, 2018-04-23
2+
* Initial release

Html.php

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
<?php
2+
3+
/**
4+
* @package Flextype Components
5+
*
6+
* @author Sergey Romanenko <awilum@yandex.ru>
7+
* @link http://components.flextype.org
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*/
12+
13+
namespace Flextype\Component\Html;
14+
15+
class Html
16+
{
17+
/**
18+
* Preferred order of attributes
19+
*
20+
* @var array
21+
*/
22+
public static $attribute_order = [
23+
'action', 'method', 'type', 'id', 'name', 'value',
24+
'href', 'src', 'width', 'height', 'cols', 'rows',
25+
'size', 'maxlength', 'rel', 'media', 'accept-charset',
26+
'accept', 'tabindex', 'accesskey', 'alt', 'title', 'class',
27+
'style', 'selected', 'checked', 'readonly', 'disabled',
28+
];
29+
30+
/**
31+
* The registered custom macros.
32+
*
33+
* @var array
34+
*/
35+
public static $macros = [];
36+
37+
/**
38+
* Registers a custom macro.
39+
*
40+
* // Registering a Html macro
41+
* Html::macro('my_element', function() {
42+
* return '<element id="flextype">';
43+
* });
44+
*
45+
* // Calling a custom Html macro
46+
* echo Html::my_element();
47+
*
48+
*
49+
* // Registering a Html macro with parameters
50+
* Html::macro('my_element', function($id = '') {
51+
* return '<element id="'.$id.'">';
52+
* });
53+
*
54+
* // Calling a custom Html macro with parameters
55+
* echo Html::my_element('flextype');
56+
*
57+
* @param string $name Name
58+
* @param Closure $macro Macro
59+
*/
60+
public static function macro(string $name, $macro)
61+
{
62+
Html::$macros[$name] = $macro;
63+
}
64+
65+
/**
66+
* Convert special characters to HTML entities. All untrusted content
67+
* should be passed through this method to prevent XSS injections.
68+
*
69+
* echo Html::toText('test');
70+
*
71+
* @param string $value String to convert
72+
* @param bool $double_encode Encode existing entities
73+
* @return string
74+
*/
75+
public static function toText(string $value, bool $double_encode = true) : string
76+
{
77+
return htmlspecialchars($value, ENT_QUOTES, 'utf-8', $double_encode);
78+
}
79+
80+
/**
81+
* Compiles an array of HTML attributes into an attribute string.
82+
* Attributes will be sorted using Html::$attribute_order for consistency.
83+
*
84+
* echo '<div'.Html::attributes($attrs).'>'.$content.'</div>';
85+
*
86+
* @param array $attributes Attribute list
87+
* @return string
88+
*/
89+
public static function attributes(array $attributes = null) : string
90+
{
91+
if (empty($attributes)) return '';
92+
93+
// Init var
94+
$sorted = [];
95+
96+
foreach (Html::$attribute_order as $key) {
97+
98+
if (isset($attributes[$key])) {
99+
// Add the attribute to the sorted list
100+
$sorted[$key] = $attributes[$key];
101+
}
102+
103+
}
104+
105+
// Combine the sorted attributes
106+
$attributes = $sorted + $attributes;
107+
108+
$compiled = '';
109+
110+
foreach ($attributes as $key => $value) {
111+
112+
if ($value === NULL) {
113+
// Skip attributes that have NULL values
114+
continue;
115+
}
116+
117+
if (is_int($key)) {
118+
// Assume non-associative keys are mirrored attributes
119+
$key = $value;
120+
}
121+
122+
// Add the attribute value
123+
$compiled .= ' '.$key.'="'.Html::toText($value).'"';
124+
}
125+
126+
return $compiled;
127+
}
128+
129+
/**
130+
* Create br tags
131+
*
132+
* echo Html::br(2);
133+
*
134+
* @param int $num Count of line break tag
135+
* @return string
136+
*/
137+
public static function br(int $num = 1) : string
138+
{
139+
return str_repeat("<br>", $num);
140+
}
141+
142+
/**
143+
* Create &nbsp;
144+
*
145+
* echo Html::nbsp(2);
146+
*
147+
* @param int $num Count of &nbsp;
148+
* @return string
149+
*/
150+
public static function nbsp(int $num = 1) : string
151+
{
152+
return str_repeat("&nbsp;", $num);
153+
}
154+
155+
/**
156+
* Create an arrow
157+
*
158+
* echo Html::arrow('right');
159+
*
160+
* @param string $direction Arrow direction [up,down,left,right]
161+
* @return string
162+
*/
163+
public static function arrow(string $direction) : string
164+
{
165+
switch ($direction) {
166+
case "up": $output = '<span class="arrow">&uarr;</span>'; break;
167+
case "down": $output = '<span class="arrow">&darr;</span>'; break;
168+
case "left": $output = '<span class="arrow">&larr;</span>'; break;
169+
case "right": $output = '<span class="arrow">&rarr;</span>'; break;
170+
}
171+
172+
return $output;
173+
}
174+
175+
/**
176+
* Create HTML link anchor.
177+
*
178+
* echo Html::anchor('About', 'http://sitename.com/about');
179+
*
180+
* @param string $title Anchor title
181+
* @param string $url Anchor url
182+
* @param array $attributes Anchor attributes
183+
* @return string
184+
*/
185+
public static function anchor(string $title, string $url = '', array $attributes = null) : string
186+
{
187+
// Add link
188+
if ($url !== '') $attributes['href'] = $url;
189+
return '<a'.Html::attributes($attributes).'>'.$title.'</a>';
190+
}
191+
192+
/**
193+
* Create HTML <h> tag
194+
*
195+
* echo Html::heading('Title', 1);
196+
*
197+
* @param string $title Text
198+
* @param int $h Number [1-6]
199+
* @param array $attributes Heading attributes
200+
* @return string
201+
*/
202+
public static function heading(string $title, int $h = 1, array $attributes = null) : string
203+
{
204+
$output = '<h'.$h.Html::attributes($attributes).'>'.$title.'</h'.$h.'>';
205+
206+
return $output;
207+
}
208+
209+
/**
210+
* Generate document type declarations
211+
*
212+
* echo Html::doctype('html5');
213+
*
214+
* @param string $type Doctype to generated
215+
* @return mixed
216+
*/
217+
public static function doctype(string $type = 'html5')
218+
{
219+
$doctypes = ['xhtml11' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
220+
'xhtml1-strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
221+
'xhtml1-trans' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
222+
'xhtml1-frame' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
223+
'html5' => '<!DOCTYPE html>',
224+
'html4-strict' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
225+
'html4-trans' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
226+
'html4-frame' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'];
227+
228+
if (isset($doctypes[$type])) return $doctypes[$type]; else return false;
229+
}
230+
231+
/**
232+
* Create image
233+
*
234+
* echo Html::image('data/files/pic1.jpg');
235+
*
236+
* @param string $file File
237+
* @param array $attributes Image attributes
238+
* @return string
239+
*/
240+
public static function image(string $file, array $attributes = null) : string
241+
{
242+
// Add the image link
243+
$attributes['src'] = $file;
244+
$attributes['alt'] = (isset($attributes['alt'])) ? $attributes['alt'] : pathinfo($file, PATHINFO_FILENAME);
245+
246+
return '<img'.Html::attributes($attributes).'>';
247+
}
248+
249+
/**
250+
* Obfuscate an e-mail address to prevent spam-bots from sniffing it.
251+
*
252+
* echo Html::email('hello@flextype.org');
253+
*
254+
* @param string $email
255+
* @return string
256+
*/
257+
public static function email(string $email) : string
258+
{
259+
return str_replace('@', '&#64;', Html::obfuscate($email));
260+
}
261+
262+
/**
263+
* Obfuscate a string to prevent spam-bots from sniffing it.
264+
*
265+
* This method obfuscate the value, randomly convert each
266+
* letter to its entity or hexadecimal representation, keeping a
267+
* bot from sniffing the randomly obfuscated letters.
268+
*
269+
* echo Html::obfuscate('hello@flextype.org');
270+
*
271+
* @param string $value
272+
* @return string
273+
*/
274+
public static function obfuscate(string $value) : string
275+
{
276+
$safe = '';
277+
278+
foreach (str_split($value) as $letter) {
279+
switch (rand(1, 3)) {
280+
case 1:
281+
$safe .= '&#'.ord($letter).';';
282+
break;
283+
case 2:
284+
$safe .= '&#x'.dechex(ord($letter)).';';
285+
break;
286+
case 3:
287+
$safe .= $letter;
288+
}
289+
}
290+
291+
return $safe;
292+
}
293+
294+
/**
295+
* Dynamically handle calls to custom macros.
296+
*
297+
* @param string $method
298+
* @param array $parameters
299+
* @return mixed
300+
*/
301+
public static function __callStatic(string $method, array $parameters)
302+
{
303+
if (isset(Html::$macros[$method])) {
304+
return call_user_func_array(Html::$macros[$method], $parameters);
305+
}
306+
307+
throw new RuntimeException("Method [$method] does not exist.");
308+
}
309+
310+
}

0 commit comments

Comments
 (0)