5 class Html extends \Rsi\Fred\Controller\View{
49 protected function addResource(&$resource,$id,$value,$options =
null){
50 if(!$id) $id = $this->_resourceIndex++;
51 if($options & self::RESOURCE_PROXY) $this->_noPush[] = $value = $this->
component(
'proxy')->add($value);
52 elseif($options & self::RESOURCE_NO_PUSH) $this->_noPush[] = $value;
53 if($options & self::RESOURCE_ASYNC) $id = $this->asyncPrefix . $id;
54 elseif($options & self::RESOURCE_DEFER) $id = $this->deferPrefix . $id;
55 $resource[$id] = $value;
62 public function addStyleSrc($source,$id =
null,$options =
null){
63 $this->
addResource($this->_styleSrc,$id,$source,$options);
75 $this->
addResource($this->_scriptSrc,$id,$source,$options);
78 protected function integrity($resource,$hash =
null){
79 if($this->_integrityHashes ===
null){
80 $this->_integrityHashes = [];
81 if($this->_integrityCacheFile){
83 $this->_integrityHashes = include($this->_integrityCacheFile);
89 $this->_integrityHashes[$resource] = $this->integrityAlgo .
'-' . base64_encode($hash);
90 \Rsi\File::export($this->_integrityCacheFile,$this->_integrityHashes,0666);
94 return $this->_integrityHashes[$resource] ??
false;
97 public function minifyFiles($type,$sources,$target =
null,$id =
null,$options =
null){
98 $target = $this->minifiedPath . $target;
99 $root = \Rsi\Http::docRoot();
100 $resource = substr($target,strlen($root));
101 $func = [$this,
'add' . ucfirst($type) .
'Src'];
102 if(!$this->_fred->debug || !rand(0,$this->debugMinifyProbability))
return call_user_func($func,$resource,$id,$options);
103 $this->
component(
'minify')->handler($type)->files(\
Rsi\Record::prefix($sources,$root),$target);
104 if($this->integrityAlgo) $this->
integrity($resource,hash_file($this->integrityAlgo,$target,
true));
105 foreach($sources as $source) call_user_func($func,$source,
null,$options);
108 public function minifyScripts($sources,$target =
null,$id =
null,$options =
null){
109 $this->
minifyFiles(
'script',$sources,$target,$id,$options);
112 public function minifyStyles($sources,$target =
null,$id =
null,$options =
null){
113 $this->
minifyFiles(
'style',$sources,$target,$id,$options);
118 $location = $this->
component(
'location');
119 $head = $this->title ? $html->_title($this->title) :
null;
120 foreach($this->_styleSrc as $source){
121 $url = $location->rewrite($source);
122 $push = !in_array($source,$this->_noPush) && \Rsi\Http::pushHeader($url,
'style');
123 $head .= $html->style(
null,[
124 'integrity' => $push ?
false : $this->
integrity($url)
127 if($this->_style) $head .= $html->style(implode(
"\n",$this->_style));
128 foreach($this->_scriptSrc as $id => $source){
129 $url = $location->rewrite($source);
130 $push = !in_array($source,$this->_noPush) && \Rsi\Http::pushHeader($url,
'script');
131 $head .= $html->script(
null,[
132 'async' => \
Rsi\Str::startsWith($id,$this->asyncPrefix),
133 'defer' => \
Rsi\Str::startsWith($id,$this->deferPrefix),
134 'integrity' => $push ?
false : $this->
integrity($url)
141 return crc32(print_r($config,
true));
145 $client_config = array_merge($this->_fred->clientConfig(),$extra_config = [
146 'controller' => $this->_controller->clientConfig()
148 $session = new \Rsi\Fred\Component\Session(get_class($this));
149 $local_config = $session->localConfig ?: [];
150 $session->localConfig = array_map([$this,
'configHash'],array_merge($local_config,$client_config));
151 if($session->configCheck && ($session->configCheck == \
Rsi\Http::getCookie(
'fred-configCheck'))){
152 foreach($client_config as $name => &$config)
if(
153 ($this->_fred->has($name) || array_key_exists($name,$extra_config)) &&
154 ($this->
configHash($config) == \
Rsi\Record::get($local_config,$name))
158 $client_config[
'check'] = $session->configCheck = \Rsi\Str::random(8);
159 if($this->mobile) $client_config[
'mobile'] =
true;
160 return ($this->_fred->debug ?
'"use strict";' :
'') .
'
162 document.addEventListener("DOMContentLoaded",function(){' .
163 implode(
"\n",$this->_script) .
'
164 fred = new rsi.Fred(' . $this->
jsonEncode($client_config) .
');' .
165 ($this->_scriptInit ?
'
166 $(document).on("fred:controller:init",function(){
167 ' . implode(
"\n",$this->_scriptInit) .
'
182 $widget_class_name = get_class($widget);
184 array_key_exists($widget_class_name,$this->widgetClassNames) ||
185 array_key_exists($widget_class_name = \
Rsi\File::basename($widget_class_name),$this->widgetClassNames)
186 ) $class_name = $this->widgetClassNames[$widget_class_name];
188 !class_exists($class_name = $this->defaultWidgetNamespace .
'\\' . $widget_class_name) &&
189 !class_exists($class_name = $this->defaultWidgetNamespace .
'\\' . str_replace($this->_controller->defaultWidgetNamespace .
'\\',
'',\
Rsi\Record::get($widget->clientConfig(),\
Rsi\Fred\
Controller\
Widget::CLASS_NAME)))
191 return new $class_name($id,$this,$widget);
195 if(!array_key_exists($id,$this->_widgets)) $this->_widgets[$id] = $this->
createWidget($id,$this->_controller->widgets[$id]);
196 return $this->_widgets[$id];
200 return array_diff(is_array($ids) ? $ids : array_keys($this->_controller->widgets),$this->renderedWidgetIds);
205 $this->renderedWidgetIds[] = $id;
207 $value = array_key_exists($id,$request->data)
208 ? $request->data[$id]
209 : (($raw = array_key_exists($id,$request->errors)) ? $request->get($id) : $this->_controller->widgets[$id]->defaultValue);
210 return $this->
widget($id)->render($value,$raw);
220 if(!$ids)
return null;
222 $class_name = array_key_exists($type = $this->_fred->client->type ?:
null,$this->builderClassNames)
223 ? $this->builderClassNames[$type]
224 : $this->builderClassNames[
null];
225 $builder =
new $class_name($this);
227 return $builder->build($ids);
232 $this->
component(
'trans')->
id($this->actionCaptionPrefix . $action,
null,$action),
233 [
'type' =>
'submit',
'id' =>
'action' . ucfirst($action),
'name' =>
'action',
'value' => $action,
'class' =>
'action']
239 foreach($this->_controller->actions(
'form') as $action) $content .= $this->
renderFormAction($action);
240 return $this->
component(
'html')->div($content,
null,
'fred-actions');
249 $this->
component(
'event')->trigger(self::EVENT_FORM,$this,[
'content' => &$content]);
250 return $this->
component(
'html')->form($content,[
'class' => $this->formClass],$this->_controller->route());
254 if($fragment = $this->_controller->fragmentId){
255 if(($str = $this->
component(
'trans')->fragment($fragment)) !==
false) print($str);
256 elseif(method_exists($this,$method =
'fragment' . ucfirst($fragment))) print(call_user_func([$this,$method]));
257 else $this->_fred->externalError(
'Unknown fragment',[
'class' => get_called_class(),
'fragment' => $fragment]);
259 elseif($redir = $this->_fred->request->redir) \Rsi\Http::redirHeader($redir);
260 else require($this->
template ?: $this->defaultTemplatePath . strtolower(\
Rsi\File::basename(get_called_class())) .
'.php');
264 return $this->_fred->client->mobile;