<?php
namespace PHPFUI;
class Form extends \PHPFUI\HTML5Element
{
use \PHPFUI\Traits\Page;
private bool $areYouSure = true;
private bool $started = false;
private array $submitValue = [];
public function __construct(protected \PHPFUI\Interfaces\Page $page, ?\PHPFUI\Submit $submit = null, string $successFunctionName = '')
{
parent::__construct('form');
$this->addAttribute('novalidate');
$this->addAttribute('data-abide');
$this->setAttribute('method', 'post');
$this->addAttribute('accept-charset', 'UTF-8');
$this->addAttribute('enctype', 'multipart/form-data');
if ($submit)
{
$this->addSubmitButtonCallback($submit, $successFunctionName);
}
}
public function addSubmitButtonCallback(\PHPFUI\Submit $submit, string $successFunctionName) : static
{
$submitButtonId = $submit->getId();
$name = $submit->getAttribute('name');
$value = $submit->getAttribute('value');
$this->submitValue[$name] = $value;
$id = $this->getId();
$this->page->addJavaScript("$(document).ready(function(){formInit($('#{$id}'),$('#{$submitButtonId}'),'{$name}','{$value}','{$successFunctionName}');})");
$js = <<<JAVASCRIPT
function formInit(form,submit,submitName,submitValue,successFunction){
form.on("submit", function(ev) {ev.preventDefault();}).on('formvalid.zf.abide',function(e){
var color=submit.css('background-color'), text=submit.html();
e.preventDefault();
var btn=$(this).find('button.submit:focus');
if (!btn.length) {/* macHack! Safari does not keep the pressed submit button in focus, so get the first */
btn=$(this).find('button.submit');
}
if(btn[0].name!=submitName||btn[0].value!=submitValue){
form.submit();/* submit the form if not the button passed for special handling */
return 0;
}
$.ajax({type:'POST',dataType:'html',data:form.serialize()+'&'+btn[0].name+'='+btn[0].value,
beforeSend:function(request){
submit.html('Saving').css('background-color','black');
request.setRequestHeader('Upgrade-Insecure-Requests', '1');
request.setRequestHeader('Accept', 'application/json');
},
success:function(response){
var data;
try{
data=JSON.parse(response);
}catch(e){
alert('Error: '+response);
}
submit.html(data.response).css('background-color',data.color);
if(successFunction>'')window[successFunction](data);
setTimeout(function(){
submit.html(text).css('background-color',color);},3000);
},
error:function (xhr, ajaxOptions, thrownError){
submit.html(ajaxOptions+': '+xhr.status+' '+thrownError).css('background-color','red');
setTimeout(function(){
submit.html(text).css('background-color',color);},3000);
},
})
})
}
JAVASCRIPT;
$js = \str_replace(["\t", "\n"], '', $js);
$this->page->addJavaScript($js);
return $this;
}
public function isMyCallback(?\PHPFUI\Submit $submit = null) : bool
{
[$name, $value] = $this->getSubmitValues($submit);
return \PHPFUI\Session::checkCSRF() && $name && ! empty($_POST[$name]) && $_POST[$name] == $value;
}
public function saveOnClick(\PHPFUI\HTML5Element $button, ?\PHPFUI\Submit $submit = null) : static
{
[$name, $value] = $this->getSubmitValues($submit);
$id = $this->getId();
$js = "var form{$id}=$(\"#{$id}\");";
$js .= "$.ajax({type:\"POST\",dataType:\"html\",data:form{$id}.serialize()+\"&{$name}={$value}\"});";
if ($this->areYouSure)
{
$js .= "form{$id}.trigger(\"reinitialize.areYouSure\")";
}
$button->addAttribute('onclick', $js);
return $this;
}
public function setAreYouSure(bool $areYouSure = true) : static
{
$this->areYouSure = $areYouSure;
return $this;
}
protected function getStart() : string
{
if (! $this->started)
{
$this->started = true;
$areYouSure = '';
if ($this->areYouSure)
{
$this->page->addTailScript('jquery.are-you-sure.js');
$id = $this->getId();
$this->page->addJavaScript('$("#' . $id . '").on("submit",function(){$("#' . $id . '").trigger("reinitialize.areYouSure")}).areYouSure({"addRemoveFieldsMarksDirty":true})');
}
if ('get' != \strtolower($this->getAttribute('method')))
{
$this->add(new \PHPFUI\Input\Hidden(\PHPFUI\Session::csrfField(), \PHPFUI\Session::csrf()));
}
}
return parent::getStart();
}
private function getSubmitValues(?\PHPFUI\Submit $submit = null) : array
{
if ($submit)
{
$name = $submit->getAttribute('name');
$value = $submit->getAttribute('value');
}
else
{
$name = $value = '';
foreach ($this->submitValue as $name => $value)
{
break;
}
}
return [$name, $value];
}
}