16 public function tag($tag,$content =
null,$attribs =
null){
17 if($content && $this->escape) $content = htmlspecialchars($content);
19 if(is_array($attribs))
foreach($attribs as $key => $value)
if(!\Rsi::nothing($value)){
21 if($value !==
true) $html .=
'="' . htmlspecialchars(is_array($value) ? implode($value) : $value) .
'"';
23 $this->escape =
false;
24 return $html .
'>' . ($content ===
false ?
'' : (is_array($content) ? implode($this->
break,$content) : $content) .
"</$tag>");
27 public function options($content,$value =
null,$attribs =
null,$assoc =
null){
28 if(is_array($options = $content)){
29 if($assoc ===
null) $assoc = \Rsi\Record::assoc($options);
31 foreach($options as $key => $descr) $content .= (is_array($descr)
32 ? $this->optgroup($this->
options($descr,$value,$assoc),[
'label' => $key])
34 ($assoc ?
' value="' . htmlspecialchars($key) .
'"' :
'') .
35 ($value ===
null ?
'' : (is_array($value) ? in_array($assoc ? $key : $descr,$value) : (strcmp($assoc ? $key : $descr,$value) ?
'' :
' selected'))) .
36 '>' . ($this->escape ? htmlspecialchars($descr) : $descr) .
'</option>'
39 $this->escape =
false;
43 public function a($content,$attribs =
null,$href =
null){
44 return $this->
tag(
'a',$content,array_merge([
'href' => $href],$attribs ?: []));
47 public function datalist($content,$attribs =
null,$id =
null){
48 return $this->
tag(
'datalist',$this->
options($content,
null,
null,
false),array_merge([
'id' => $id],$attribs ?: []));
51 public function div($content,$attribs =
null,$class =
null,$id =
null){
52 return $this->
tag(
'div',$content,array_merge(compact(
'class',
'id'),$attribs ?: []));
55 public function form($content,$attribs =
null,$action =
null,$method =
'post',$enctype =
'multipart/form-data'){
56 return $this->
tag(
'form',$content,array_merge(compact(
'action',
'method',
'enctype'),$attribs ?: []));
59 public function img($content,$attribs =
null,$alt =
null){
60 $auto_width = \Rsi\Record::get($attribs,
'width') ===
true;
61 $auto_height = \Rsi\Record::get($attribs,
'height') ===
true;
62 $auto_background = \Rsi\Record::get($attribs,
'background') ===
true;
63 if($auto_width || $auto_height || $auto_background){
64 $log = $this->_fred->component(
'log');
65 if(strpos($filename = $content,
'//') !==
false) $filename = \Rsi\Http::ensureProtocol($filename);
66 elseif(substr($filename,0,1) ==
'/') $filename = \Rsi\Http::docRoot() . $filename;
67 else $filename = \Rsi\Http::docRoot() . dirname($_SERVER[
'REQUEST_URI'] ??
null) .
'/' . $filename;
68 $width = $height =
null;
70 unset($attribs[
'background']);
72 $image = \Rsi\Image::fromFile($filename);
73 $width = imagesx($image);
74 $height = imagesy($image);
75 $log->debug(
"Auto-background generation for '$filename' ($width x $height)",__FILE__,__LINE__);
76 $background =
'background: linear-gradient(to bottom';
78 $red = $green = $blue = $count = 0;
80 $rgb = imagecolorsforindex($image,imagecolorat($image,min($x * $width / 100,$width - 1),min($y * $height / 100,$height - 1)));
82 $green += $rgb[
'green'];
83 $blue += $rgb[
'blue'];
86 $background .=
',' . \Rsi\Color::toHex([$red / $count,$green / $count,$blue / $count]) .
" $y%";
89 if(array_key_exists(
'style',$attribs)) $attribs[
'style'] .=
';' . $background;
90 else $attribs[
'style'] = $background;
96 if($auto_width || $auto_height)
try{
97 if($width ===
null) list($width,$height) = getimagesize($filename);
98 if($auto_width) $attribs[
'width'] = $width;
99 if($auto_height) $attribs[
'height'] = $height;
103 if($auto_width) unset($attribs[
'width']);
104 if($auto_height) unset($attribs[
'height']);
107 return $this->
tag(
'img',
false,array_merge([
'src' => $content,
'alt' => $alt ?: \
Rsi\File::basename($content),
'title' => $alt],$attribs ?: []));
110 public function input($content,$attribs =
null,$type =
null,$name =
null,$options =
null){
113 $radio = $type ==
'radio';
115 foreach($options as $key => $label){
116 if(
$escape) $label = htmlspecialchars($label);
117 $html .= $this->label(
119 \Rsi::nothing($key) ? (is_array($key) ? [
''] :
'') : $key,
120 array_merge($attribs ?: [],[
'checked' => is_array($content) ? in_array($key,$content) : is_scalar($content) && !strcmp($key,$content)]),
122 $name . ($radio ?
'' :
"[$key]")
129 if(is_array($content)){
131 foreach($content as $key => $value) $html .= $this->
input($value,$attribs,$type,$name ? $name .
'[' . $key .
']' : $key) .
$this->break;
134 return $this->
tag(
'input',
false,array_merge([
'value' => $content] + compact(
'type',
'name'),$attribs ?: []));
137 public function meta($content,$attribs =
null,$name =
null){
138 return $this->
tag(
'meta',
false,array_merge([
'name' => $name,
'content' => $content],$attribs ?: [])) .
$this->break;
141 public function script($content,$attribs =
null,$srcs =
null,$type =
'text/javascript'){
142 if($content) $content =
"\n/* <![CDATA[ */\n$content\n/* ]]> */\n";
143 if(!is_array($srcs)) $srcs = [$srcs];
145 foreach($srcs as $src) $html .= $this->
tag(
'script',$content,array_merge(compact(
'src',
'type'),$attribs ?: [])) .
$this->break;
149 public function select($content,$attribs =
null,$value =
null,$assoc =
null,$name =
null){
150 return $this->
tag(
'select',$this->
options($content,$value,
null,$assoc),array_merge([
'name' => $name],$attribs ?: []));
153 public function span($content,$attribs =
null,$class =
null,$id =
null){
154 return $this->
tag(
'span',$content,array_merge(compact(
'class',
'id'),$attribs ?: []));
157 public function style($content,$attribs =
null,$srcs =
null,$type =
'text/css'){
158 if(!$srcs)
return $this->
tag(
'style',$content,$attribs);
159 if(!is_array($srcs)) $srcs = [$srcs];
161 foreach($srcs as $src) $html .= $this->
tag(
'link',
false,array_merge([
'rel' =>
'stylesheet',
'type' => $type,
'href' => $src],$attribs ?: [])) .
$this->break;
165 public function table($content,$attribs =
null,$columns =
null){
166 if(is_array($content)){
167 $header = $footer = $body =
'';
168 $headers = $footers = [];
169 if(!$columns) $columns = array_fill_keys(array_keys(\
Rsi\Record::value($content)),[]);
170 foreach($columns as $key => $column){
171 $header .= $this->
tag(
'th',$headers[$key] = $column[
'header'] ?? $key,$column[
'attribs'] ??
null);
172 $footer .= $this->
tag(
'th',$footers[$key] = $column[
'footer'] ??
null,$column[
'attribs'] ??
null);
174 foreach($content as $record){
176 foreach($columns as $key => $column) $row .= $this->
tag(
'td',$record[$key] ??
null,$column[
'attribs'] ??
null);
180 (array_filter($headers) ? $this->
tag(
'thead',$header) . $this->break :
'') .
181 (array_filter($footers) ? $this->
tag(
'tfoot',$footer) . $this->break :
'') .
182 $this->
tag(
'tbody',$body);
184 return $this->
tag(
'table',$content,$attribs);
187 public function textarea($content,$attribs =
null,$name =
null){
188 return $this->
tag(
'textarea',$content ?:
null,array_merge([
'name' => $name],$attribs ?: []));
191 public function th($content,$attribs =
null,$scope =
'col'){
192 return $this->
tag(
'th',$content,array_merge([
'scope' => $scope],$attribs ?: []));
195 public function __call($func_name,$params){
196 if(substr($func_name,0,1) ==
'_'){
197 $this->escape =
true;
198 $func_name = substr($func_name,1);
201 array_unshift($params,$func_name);
204 return call_user_func_array([$this,$func_name],$params);