FormEntity.php

<?php

namespace Doc;

class FormEntity extends \Doc\Entity {

    protected $propAttribute = 'name';


    public function fillSelf($removeAPIData){
        $this->addHiddenInput('id','');
        $table = $this->table;
        $lookup = $this->lookupStr;
        $form = $this->node;
        $formName = $this->options['formName'] ?? null;
        // var_dump($table);
        // exit;
        // if ($viewName!=null){
            // $form->innerHTML = "\n".'<input type="hidden" name="view_name" value="'.$viewName.'"/>'."\n".$form->innerHTML;
        // }
        // if ($formName!=null){
            // $form->innerHTML = "\n".'<input type="hidden" name="form_name" value="'.$formName.'"/>'."\n".$form->innerHTML;
        // }
        $form->setAttribute('method','POST');
        $form->setAttribute('action','/submit_auto_form/');
        if ($this->doesHaveFileInput()){
            $form->setAttribute('enctype','multipart/form-data');
        }
        if ($table!=null){
            $this->addHiddenInput('autoschema_table',$table);
        }
        if ($lookup!=null){
            // echo "\n\n".$lookup."\n\n";
            $this->addHiddenInput('autoschema_lookup',$lookup);
        }
        if ($formName!=null){
            $this->addHiddenInput('autoschema_form',$formName);
        }
        if ($this->new&&$this->initData!=null){
            $this->addHiddenInput('autoschema_initData',$this->initDataStr);
            // $data = $this->initData;
            // foreach ($data as $key=>$value){
                // $this->addHiddenInput($key,$value);
            // }
        }
        if (!$this->new){
            parent::fillSelf($removeAPIData);
        }
    }

    public function setFormInputValue($node,$value){
        $tagName = strtolower($node->tagName);
        $type = strtolower($node->getAttribute('type'));
        // echo "\n\n---------".$tagName.':'.$type."\n\n";
        // exit;
        if ($tagName=='textarea'){
            $node->innerHTML = $value;
        } else if ($tagName=='input'&&$type=='file'){
            // echo "it's a file input";
            $attr = $node->getAttribute('name');
            $queryStr = "//img[@for='{$attr}']";
            $xPath = new \DOMXPath($this->doc);
            $holderList = $xPath->query($queryStr);
            $fileHolder = $holderList[0]??null;
            if(is_object($fileHolder)){
                $fileHolder->setAttribute('src',$value);
                $attr = $fileHolder->getAttribute($attr);
                $fileHolder->removeAttribute($attr);
                $fileHolder->setAttribute('data-name',$attr);
            }
            // exit;
            // echo 'fileholder';
            // exit;
        } else if ($tagName=='input'){
            $node->setAttribute('value',$value);
        } 
        return true;
    }

    public function enableEditMode(){

    }

    public function submit($submitData){
        // var_dump($this->initData);
        // exit;
        // $this->insertHiddenIdInput($this->node);
        $fields = $this->getInputs();
        $table = $this->table;
        $filesToUpload = [];
        foreach ($fields as $index => $data) {
            $name = $data['name'];
            $required = $data['required'];
            $type = $data['type'];
            $tag = $data['tag'];
            $input = $data['input'];
            if ($type=='file'){
                $file = $_FILES[$name]?? null;
                if ($file==null)$pass=false;
                $filesToUpload[] = ['file'=>$_FILES[$name],
                                    'inputData'=>$data
                                    ];
                unset($_FILES[$name]);
                if ($pass)continue;
            } else {
                $pass = $this->verify($data, $submitData[$name] ?? null);
            }
            if (!$pass) {
                throw new \Exception("Input '{$name}' failed verification");
            }
            $saveData[$name] = $submitData[$name];
            unset($submitData[$name]);
        }
        if (count($submitData) > 0) {
            // print_r($submitData);
            throw new \Exception("More data was sent to the server than was requested.");
        }
        foreach ($this->initData as $key=>$value){
            $saveData[$key] = $value;
        }
        foreach ($filesToUpload as $index=>$data){
            $file = $data['file'];
            $inputData = $data['inputData'];
            // print_r($this->options);
            // exit;
            $fileName = $this->schemaDoc->uploadFile($file);
            if ($fileName===false)continue;
            $urlPath = '/'.$this->schemaDoc->imageUrlPrefix.'/'.$fileName;
            $urlPath = str_replace(['///','//'],'/',$urlPath);
            $saveData[$inputData['name']] = $urlPath;
        }
        $bean = \RDB::dispense($table);
        $bean->import($saveData);
        \RDB::store($bean);
    }

    protected function doesHaveFileInput(){
        $form = $this->node;
        $x = new \DOMXpath($this->doc);
        $inputs = $x->query('//input[@type="file"]');
        foreach ($inputs as $input){
            $parent = $input;
            while ($parent==$parent->parentNode){
                if ($parent==$form)return true;
            }
        }
        return false;
    }

    protected function addHiddenInput($name,$value){
        $xPath = new \DOMXpath($this->doc);
        $existing = $xPath->query('//input[@type="hidden"][@name="'.$name.'"]', $this->node);
        if ($existing->count()>1){
            throw new \Exception("There are multiple hidden inputs with the same name");
        } else if ($existing->count()==0){
            $this->node->innerHTML = "\n".'<input type="hidden" name="'.$name.'" value="'.$value.'"/>'."\n".$this->node->innerHTML;
        } else {
            $input = $existing->item(0);
            $input->value = $value;
        }
    }
    protected function getInputs()
    {
        $xPath = new \DOMXpath($this->doc);
        $htmlInputs = $xPath->query('.//*[@name]',$this->node);
        $inputs = [];
        foreach ($htmlInputs as $input) {
            if ($input->tagName == 'form') {
                continue;
            } 
            $prefix = 'autoschema_';
            if (substr($input->getAttribute('name'),0,strlen($prefix))==$prefix){
                continue;
            }

            $data = [];
            $data['name'] = $input->getAttribute('name');
            $data['required'] = $input->hasAttribute('required');
            $data['type'] = $input->getAttribute('type');
            $data['tag'] = $input->tagName;
            $data['input'] = $input;
            if (isset($inputs[$data['name']])) {
                throw new \Exception("Input '" . $data['name'] . "' occurs twice on the form, which FormTools doesn't know how to handle.");
            }
            $inputs[$data['name']] = $data;
            continue;
        }
        return $inputs;
    }
    protected function verify($inputData, $value)
    {
        //see $this->getInputs() to see what is extracted
        extract($inputData);
        if (empty($value) && $required) {
            return false;
        }

        if ($type == 'phone') {
            $clean = preg_replace('/[^0-9]/', '', $value);
            if (strlen($clean) == 10
                || strlen($clean) == 11) {
                return true;
            }
            return false;
        }
        if ($type == 'text') {
            return true;
        }
        if ($type == 'email') {
            $email = filter_var($value, FILTER_VALIDATE_EMAIL);
            if ($email === false) {
                return false;
            }

            return true;
        }

        return true;
    }



}