Jump to content
pwFoo

Template2Form module / helper

Recommended Posts

Hi,

during work on some own modules (frontend content manager, frontend users) I noticed my need of a helper module.

Template2Form (working title) is a module to build a form based on fields get from a page object or a template file (tmp fake page object). During build process each field could be hooked in to modify it. Also it's possible to modifiy form, submit button and form fields via function params.

It's my first (basic / dev state) module I post here...  :-[

If it will be useable I have to clean up and comment the code well...

template2form class

<?php

/**
 * Processwire 'template2form' module
 * 
 * template2form - generate form from page / template fields
 * 
 * @author pwFoo
 * @since 2014-07-18
 * 
 * ProcessWire 2.x
 * Copyright (C) 2011 by Ryan Cramer
 * Licensed under GNU/GPL v2, see LICENSE.TXT
 *
 * http://www.processwire.com
 * http://www.ryancramer.com
 */
class Template2Form extends WireData implements Module {
    
    /**
     * @var object $form generated form object
     */
    public $form;
    
    /**
     * @var array $option multidimensional array with options
     */
    private $option;
    
    /**
     * getModuleInfo is a module required by all modules to tell ProcessWire about them
     * @return array
     */
    public static function getModuleInfo() {
        return array(
            'title' => 'Template2Form',
            'summary' => 'Generate form from template fields',
            'version' => '0.0.1',           
        );
    } 
    
    /**
     * Default module and form options
     * @var array $defaultOptions static mutlidimensional array with default options
     */
    public static $defaultOptions = array(
        'page'                  => null,
        'template'              => null,
        'prefillFormFields'     => null,
        'jquery'                => null,
        'form'                  => array('method' => 'post', 'action' => '', 'id' => 'login', 'name' => 'login'),
        'formSubmit'            => array('id' => 'submit', 'name' => 'submit', 'value' => 'Submit'),
        'formFields'            => null,
    );
    
    public function init() {
        $this->addHookAfter('Template2Form::buildField', $this, 'hookingFormField', array('priority'=>20));
    }

    /**
     * Set / merge module and form options
     * @param array $options Array with given options
     * @return null
     */
    private function setOptions (array $options = null) {
        if($options != null && is_array($options)) {
            $this->option = array_replace_recursive(self::$defaultOptions, $options);

            // Use template instead of page if given
            if ($this->option['template] !== null) {
                $this->option['page'] = $this->fakePage($this->option['template']);
            }
            // No template or page? Use current page...
            elseif ($this->option['template'] === null) {
                $this->option['page'] = $this->page;
            }
            if ($this->option['jquery']) {
                $this->modules->get('JqueryCore');
            }
        } 
        else {
            $this->option = self::$defaultOptions;
	}
    }
    
    /**
     * Generate the form object
     * @param array $options Set of optional and needed settings
     * @return object Generated form
     */
    public function getForm (array $options = null) {
        $this->setOptions($options);  
        $this->form = $this->buildForm ();
        return $this->form;
    }

    /**
     * Generate the form object from given fields
     * @return object Generated form
     */
    private function buildForm () {
        $form = $this->modules->get('InputfieldForm');
        $form = $this->setFormAttr($form);
        
        // Get fields to build the form
        $fields = $this->templates->get($this->option['page']->template)->fields;
        
        foreach ($fields as $field) {
            $f = $this->buildField ($field);    // Get Inputfield object
            if ($f !== NULL) $form->append($f); // Remove NULLed fields from from...
        }
        $form->append($this->addSubmitButton());
        return $form;
    }
   
    /**
     * Set form attributes and return the object
     * @param object $form
     * @return object Form with added attributes
     */
    protected function ___setFormAttr($form) {
        $form->id = $this->option['form']['id'];
        $form->name = $this->option['form']['name'];
        $form->action = $this->option['form']['action'];
        $form->method = $this->option['form']['method'];
        return $form;
    }
    
    /**
     * Generate Inputfield object from given field object
     * @param object $field Page field object
     * @return object 
     */
    protected function ___buildField ($field) {
        return $field->getInputfield($this->option['page']);
    }
    
    /**
     * Modify the current field object by hook in after buildField function
     * @param object $event 
     */
    protected function ___hookingFormField ($event) {
        $field = $event->return;
        $hook = $this->option['formFields'][$field->name]; 
        
        // Remove selected field...
        if ($hook['remove'] == true) {
            $event->return = NULL;
        }
        // prefill form fields from page value...
        elseif ($this->option['prefillFormFields'] && $event->page->get($field->name)) { 
            $hook['set']['value'] = $event->page->get($field->name);
        }
        
        if (!isset($hook)) return;   // nothing to do with this field...
        
        // Set form field values...
        elseif (is_array($hook['set'])) {
            foreach ($hook['set'] as $key => $value) {
                $field->set($key, $value);
            }
            $event->return = $field;
        }
    }
    
    /**
     * Build the form submit button
     * @return object form submit Inputfield
     */
    protected function ___addSubmitButton() {
        $btn = $this->modules->get('InputfieldSubmit');
        $btn->attr('id', $this->option['formSubmit']['id']);
        $btn->attr('name', $this->option['formSubmit']['name']);
        $btn->attr('value', $this->option['formSubmit']['value']);
        
        return $btn;
    }
    
    /**
     * Rendering the current form
     * @return string Rendered form as html code
     */
    public function ___formRender() {
        return $this->form->render();
    }
    
    /**
     * Process form data if send
     * @return object Processed form data
     */
    public function ___formProcess() {
        $submit = $this->option['formSubmit']['id'];
        if(!$this->input->post->$submit) return NULL;    // form NOT submitted...

        $processedForm = $this->form->processInput($this->input->post); // form api process form values
            
        if(!$this->form->getErrors()) return $processedForm;    // form processed: OK
        else return false;   // form send with errors
    }

    /**
     * Make fake page and assign needed template
     * @param string $tpl Template to assign
     * @return object Generated fake page to work with
     */
    private function fakePage($tpl) {
        $fakePage = new Page();
        $fakePage->template = $tpl;
        return $fakePage;
    } 
    
    /**
     * jsConfig settings needed by wysiwyg editor
     * @return string Basic JavaScript config
     */
    public function ___jsConfig () {
        $jsConfig = $this->config->js();
        $jsConfig['debug'] = $this->config->debug;                                                          
        $jsConfig['urls'] = array(     
            'root' => $this->config->urls->root,
            'admin' => $this->config->urls->admin,
            'modules' => $this->config->urls->modules,                    
            'core' => $this->config->urls->core,                                
            'files' => $this->config->urls->files,                     
            'templates' => $this->config->urls->templates,                                                   
            'adminTemplates' => $this->config->urls->adminTemplates,             
        );                                                      
        return '<script type="text/javascript">var config = ' . json_encode($jsConfig) . '</script>';       
    }
}

Usage examples

$t2f = $modules->get('Template2Form');

// Remove field 'headline' and 'body' from form
$hookFormFields['headline'] = array('remove' => true);
$hookFormFields['body'] = array('remove' => true);

// Set / Overwrite field attributes / values like you could do with form api
$hookFormFields['title'] = array('set' => array('value' => 'CustomTitle...', 'type' => 'password'));
$hookFormFields['summary'] = array('set' => array('value' => 'My overwritten summary...'));

// Overwrite submit button attributes (default: id, name, value)
$hookFormSubmit = array('value' => 'Speichern');

/* 
* Build the multidemensional array
* page (object) or template (string) -- to build the form from
* prefillFormFields -- prefill fields (for example to build a frontend edit page
* jquery -- Load JqueryCore module (during getForm() call)
* form -- set form attributes / values
* formFields -- array to set field values / attributes, take a look at form api examples
* formSubmit -- set form submit button attributes / values
*/
$formOptions = array('page' => $page, 'template' => null, 'prefillFormFields' => true, 'jquery' => true 'formFields' => $hookFormFields, 'formSubmit' => $hookFormSubmit);

// Generate the form and set options above
$t2f->getForm($formOptions);

// process form and return processed form date
$process = $t2f->formProcess();
if ($process === NULL)      // form not sent
elseif ($process === false) // form sent, but with errors
elseif ($process == true)   // form sent without errors

// Render form...
$form = $t2f->formRender();

echo '<html><head>'; 

// jsConfig needed by ckeditor
echo $t2f->jsConfig() . "\n"; 

// outpunt needed scripts for inputfield modules, ...
foreach ($config->scripts as $file) { echo "<script type='text/javascript' src='$file'></script>\n"; }
foreach ($config->styles as $file) { echo "<link type='text/css' href='$file' rel='stylesheet' />\n"; } 

echo '</head><body>';

echo $form;    // output form

echo '</body></html>';
  • Like 9

Share this post


Link to post
Share on other sites

Changed some little things (array_merge changed to array_replace_recursive because of sub arrays at options).

Seems to work now how expected.

Because nobody other than me needs such a module I won't release it as a module and simply test and use it inside my application.

Share this post


Link to post
Share on other sites

Changed some little things (array_merge changed to array_replace_recursive because of sub arrays at options).

Seems to work now how expected.

Because nobody other than me needs such a module I won't release it as a module and simply test and use it inside my application.

Don't be discouraged by the absence of replies within the first couple of days. It sounds interesting and like something that could be useful to others as well, so keep at it.

  • Like 2

Share this post


Link to post
Share on other sites

Ok, helper module is used by my own frontend user module (at the moment a simple login, register, logout module) which is extendable (email activiation, backend plugins,...) and it seems to work fine.

But before I can release it as a public module I have to do some more clean up and comments on the code... ;)

Also feedback is appreciated because it's my first module.

  • naming convention?
  • what could/ should be improved or simplyfied?

Share this post


Link to post
Share on other sites

Modules based on template2form module

  • FrontendUsers (basically done - rewrite, optimize and add optional features)
    login, logout, register frontend users, backend plugins to implement for example ldap auth (login, register form added as templates to work with template2form module)
     
  • FrontendContentManager (edit function works as proof of concept, but have to be improved and tested with repeater fields and language support...)
    edit and create content as frontend user 
     
  • FrontendProfile (planned)
    user pages / profiles, owner editable, extendable

Template2Form... shouldn't it be renamed...?!

Somewhere I read an recommendation about module names. Because of form building it could be start with "Form..."?

Any idea?

  • Like 1

Share this post


Link to post
Share on other sites

Thinking about how to build my login and register form during module rewrite...

Build a register form based on a PW template (simply add fields to template to expand the register form generated by template2form module...) could be nice, but what's with a simple login form?

Login form via template2form needs a template "form_login" with the fields "username" and "password". Should such a form better build via form api at source code? Is a template file with to fields to much overhead or see you any advantage to do it that way?

But with the module the form process is simplyfied (needed code is implemented).

template2form is primary build as a universal module / helper to generate a page frontend edit form. Could be also used for login and register forms, but should I do...?

Share this post


Link to post
Share on other sites

After some more ideas and a rewrite again...
Should be renamed to FormHelper.
 
Module can create forms by 
1) page object
2) template (fields)
3) array of field data (new)
 
It's possible to skipFields (array of field names), clearFormValues (field values removed), changeable form and submit button values, take care of jsConfig and also JqueryCore module load.
So ckeditor works out of the box (if output order is correct at template...)
 
Example how to build a login form with username and password fields...

$fh = $modules->get('FormHelper');

// Create a username form field -- fieldVars 'name' is required to build $field->name
$fieldVars = array('name' => 'username', 'label' => 'Username', 'required' => true);
$fieldAttr = array('id+name' => 'username');
$field = array('module' => 'InputfieldText', 'vars' => $fieldVars, 'attr' => $fieldAttr);
$formFields[] = $field;

// Second form field... password
$fieldVars = array('name' => 'password', 'label' => 'Password', 'required' => true);
$fieldAttr = array('id+name' => 'password', 'type' => 'password');
$field = array('module' => 'InputfieldText', 'vars' => $fieldVars, 'attr' => $fieldAttr);
$formFields[] = $field;

// Change submit button value from "Submit" to "Login"
$formSubmit = array('attr' => array('value' => 'Login'));

// Generate the form
$fh->createForm(array('formSubmit' => $formSubmit, 'formFields' => $formFields));

// process form
$process = $fh->formProcess();

// check result of form process
if ($process === NULL) // not send
elseif ($process == true) // send, without errors
elseif ($process === false) // send, but with errors

$form = $fh->render();  // returns rendered form 

echo '<html><head>'; 

// jsConfig needed by wysiwyg editors
echo $fh->jsConfig() . "\n"; 

// outpunt needed scripts for inputfield modules, ...
foreach ($config->scripts as $file) { echo "<script type='text/javascript' src='$file'></script>\n"; }
foreach ($config->styles as $file) { echo "<link type='text/css' href='$file' rel='stylesheet' />\n"; } 

echo '</head><body>';
echo $form;    
echo '</body></html>';

 
 
Generate form of current page (with ckeditor loaded for body field... jquery is needed)

$fh->createForm(array('jquery' => true));

Generate form from given page object

$fh->createForm(array('page' => $pages->get('/')));

// or without prefilled form field values
$fh->createForm(array('page' => $pages->get('/'), 'clearFormValues' => true));

And form based on template fields

$fh->createForm(array('template' => 'sitemap'));

Known bug with form generated based on a template instead an existing page! You get an error if a form should be generated from a template with fiel fields (like images)! Because of a fakePage object You'll get this error message.


Error: Exception: New page '/pwdev//' must be saved before files can be accessed from it (in /volume1/web/pwdev/wire/core/PagefilesManager.php line 240)

#0 /volume1/web/pwdev/wire/core/PagefilesManager.php(211): PagefilesManager->path()
#1 /volume1/web/pwdev/wire/core/PagefilesManager.php(67): PagefilesManager->createPath()
#2 /volume1/web/pwdev/wire/core/PagefilesManager.php(55): PagefilesManager->init(Object(Page))
#3 /volume1/web/pwdev/wire/core/Page.php(1625): PagefilesManager->__construct(Object(Page))
#4 /volume1/web/pwdev/wire/core/Pagefiles.php(74): Page->filesManager()
#5 /volume1/web/pwdev/wire/core/Pagefiles.php(58): Pagefiles->setPage(Object(Page))
#6 /volume1/web/pwdev/wire/modules/Fieldtype/FieldtypeImage.module(33): Pagefiles->__construct(Object(Page))
#7 /volume1/web/pwdev/wire/core/Fieldtype.php(374): FieldtypeImage->getBlankValue(Object(Page), Object(Field))
#8 /volume1/web/pwdev/wire/core/Page.php(760): Fieldtype->getDefaultValue(Object(Page), Object(Field))
#9 /volume1/web/pwdev/wire/core/Page.p

To create new pages with FormHelper your module have to create the page first.

Maybe there is a solution... but I don't know at the moment.

Also it's not a problem for my needs. Editing pages works fine and if a module try to create a new page it simply should saved via api before FormHelper build the form...

  • Like 1

Share this post


Link to post
Share on other sites

The latest (and first build *g*) of FormHelper module.

(Untested with repeater fields or multi language pages)

<?php
/**
 * Processwire 'FormHelper' module
 * 
 * Generate forms from pages, templates or input data
 * 
 * @author pwFoo
 * @since 2014-09-13
 * 
 * ProcessWire 2.x
 * Copyright (C) 2011 by Ryan Cramer
 * Licensed under GNU/GPL v2, see LICENSE.TXT
 *
 * http://www.processwire.com
 * http://www.ryancramer.com
 */
class FormHelper extends WireData implements Module {
    
    protected $form;
    protected $field;
    protected $submitBtn;
    protected $option;
    
    /**
     * getModuleInfo is a module required by all modules to tell ProcessWire about them
     * @return array
     */
    public static function getModuleInfo() {
        return array(
            'title' => 'FormHelper',
            'summary' => 'Generate and process forms from page / template fields or given field parameters',
            'version' => '0.0.1',           
        );
    } 
    
    /**
     * Default module and form options
     * @var array $defaultOptions static mutlidimensional array with default options
     */
    private static $defaultOptions = array(
        // Use page, template or given formFields array data
        'page'                  => null,
        'template'              => null,
        'formFields'            => null,
        
        // form, fields and submit button basics
        'form' =>  array(
            'module' => 'InputfieldForm',
            'vars' => array('method' => 'post', 'action' => ''),
            'attr' => array('id+name' => 'formhelper'),
        ),
        'formSubmit' =>  array(
            'module' => 'InputfieldSubmit',
            'attr' => array ('id' => 'submit', 'name' => 'submit', 'value' => 'Submit'),
        ),
        'formFields' => null,
        
        // module options
        'clearFormValues' => null,
        'jquery' => null,
    );
    
    /**
     * Set / merge module and form options
     * @param array $options Array with given options
     * @return null
     */
    private function setupOptions (array $options = null) {
        if($options != null && is_array($options)) {
            $this->option = array_replace_recursive(self::$defaultOptions, $options);
        }
        else {
            $this->option = self::$defaultOptions;
	}
        
        // Use template instead of page if given
        if ($this->option['template'] !== null) {
            $this->option['page'] = $this->fakePage($this->option['template']);
        }
        // No template or page set? Also no formFields defined? Use current page...
        elseif ($this->option['page'] === null && $this->option['formFields'] === null) {
            $this->option['page'] = $this->page;
        }
        
        // jQuery module should be loaded early because it's needed by for example ckeditor
        if ($this->option['jquery']) {
            $this->modules->get('JqueryCore');
        }
    }
    
    /**
     * Generate the form object from given fields
     * @return object Generated form
     */
    public function ___createForm (array $options = null) {
        $this->setupOptions($options);  // set options

        // create form field / wrapper
        $this->form = $this->setObj($this->option['form']);
        
        // Get inputfields from page object or given template
        if ($this->option['page'] || $this->option['template']) {
            $inputfields = $this->getFormInputfields();
        }
        // ... or a user given form data structure
        elseif ($this->option['formFields'] !== null && is_array($this->option['formFields'])) {
            $inputfields = $this->createFormFields();
        }
        
        // add fields to form...
        foreach($inputfields as $inputfield) {
            if ($field = $this->prepareField($inputfield)) {
                $this->form->add($field);
                $this->field[$field->attr('name')] = $field;
            }
        }
        
        // add submit button
        $this->submitBtn = $this->setObj($this->option['formSubmit']);
        $this->form->add($this->submitBtn);
        
        return $this->form;
    }

    /**
     * 
     */
    protected function ___prepareField($field) {
        if(in_array($field->name, $this->option['skipFields'])) return null;    // remove field
        if ($this->option['clearFormValues']) $field->value = null; // set value to empty
        return $field;
    }
    
    /**
     * Generate inputfields from given page object fields
     * @return object Generated field
     */
    protected function getFormInputfields () {
        if (!$this->option['page']) { 
            $this->option['page'] = $this->fakePage($this->option['template']);
        }
        return $this->option['page']->getInputfields();
    }
    
    /**
     * Generate form fields based on given data array
     * @return object Generated field
     */
    protected function createFormFields() {
        foreach ($this->option['formFields'] as $formField) {
            $field = $this->setObj($formField);
            $inputfields[$field->name] = $field;
        }
        return $inputfields;
    }
    
    /**
     * Rendering the current form
     * @return string Rendered form as html code
     */
    public function ___render() {
        return $this->form->render();
    }
    
    /**
     * Process form data if send
     * @return object Processed form data
     */
    public function ___formProcess() {
        $submit = $this->submitBtn->get('name');
        if(!$this->input->post->$submit) return NULL;    // form NOT submitted...

        $processedForm = $this->form->processInput($this->input->post); // form api process form values
            
        if(!$this->form->getErrors()) return $processedForm;    // form processed: OK
        else return false;   // form send with errors
    }
    
    /**
     * Generate a field / form object
     * @param array $arr Needed values to create the object
     * @return object Generated field object
     */
    private function setObj($arr) {
        $obj = $this->modules->get($arr['module']);
        
        $this->setObjVars($obj, $arr['vars']);
        $this->setObjVars($obj, $arr['attr']);
        
        return $obj;
    }

    /**
     * Set field object variables
     * @param object $obj field object by reference
     * @param array $arr field variable values
     */
    private function setObjVars(&$obj, $arr) {
        foreach ($arr as $key => $value) {
            $obj->set($key, $value);
        }
    }
    
    /**
     * Set field object attribues
     * @param object $obj field object by reference
     * @param array $arr field attribute values
     */
    private function setObjAttr(&$obj, $arr) {
        foreach ($arr['attr'] as $key => $value) {
            $obj->attr($key, $value);
        }
    }
    
    /**
     * Make fake page and assign needed template
     * @param string $tpl Template to assign
     * @return object Generated fake page to work with
     */
    private function fakePage($tpl) {
        $fakePage = new Page();
        $fakePage->template = $tpl;
        return $fakePage;
    } 
    
    /**
     * jsConfig settings needed by wysiwyg editor
     * @return string Basic JavaScript config
     */
    public function ___jsConfig () {
        $jsConfig = $this->config->js();
        $jsConfig['debug'] = $this->config->debug;                                                          
        $jsConfig['urls'] = array(     
            'root' => $this->config->urls->root,
            'admin' => $this->config->urls->admin,
            'modules' => $this->config->urls->modules,                    
            'core' => $this->config->urls->core,                                
            'files' => $this->config->urls->files,                     
            'templates' => $this->config->urls->templates,                                                   
            'adminTemplates' => $this->config->urls->adminTemplates,             
        );                                                      
        return '<script type="text/javascript">var config = ' . json_encode($jsConfig) . '</script>';       
    }
}

Share this post


Link to post
Share on other sites

Where can I download your module? I don't see any GitHub or any other link. I believe I need to copy the above code and create a module in PW.

I would like to test your module. Thanks!

Share this post


Link to post
Share on other sites

Hello fmgujju,

after diving deeper into form api I rewrite the module code again. I try to get it more flexible and easier / much shorter...

  • Minor options / parameter changes
  • Feature to merge (maybe also replace and insert at position...) page / template fields with additional values / overwrite from array data
  • get the form object and do whatever you want via form api (before render the form) ;)

At the moment you can copy the module code above to do some tests...
https://processwire.com/talk/topic/7508-template2form-module-helper/?p=73255

Maybe I can update the module code or maybe build a release until the end of the week...

Share this post


Link to post
Share on other sites

Here an updated / reworked module version...

<?php
/**
 * Processwire 'FormHelper' module
 * 
 * Generate forms from pages, templates or input data
 * 
 * @author pwFoo
 * @since 2014-09-13
 * 
 * ProcessWire 2.x
 * Copyright (C) 2011 by Ryan Cramer
 * Licensed under GNU/GPL v2, see LICENSE.TXT
 *
 * http://www.processwire.com
 * http://www.ryancramer.com
 */
class FormHelper extends WireData implements Module {
    
    protected $form;
    protected $submitBtn;
   
    protected $cfg = array(
        'page'              => null,
        'template'          => null,
        'clearFormValues'   => null,
        'jquery'            => null,
        'jsconfig'          => null,
        // form default settings
        'form'              => array(
            'module'    => 'InputfieldForm',
            'vars'      => array('method' => 'post', 'action' => ''),
            'attr'      => array('id+name' => 'formhelper'),
        ),
        'submit'            => array(
            'module'    => 'InputfieldSubmit',
            'attr'      => array ('id' => 'submit', 'name' => 'submit', 'value' => 'Submit'),
        ),
        'fields'            => null,
        /*
         * 'fields'     => array(
         *      'username' => array(
         *          'module'    => 'InputfieldText',
         *          'position'  => 'insertBefore:password',                                                     // "insert method" [":" "reference field"]
         *          'vars'      => array('name' => 'username', 'label' => 'Username', 'required' => true),      // var "name" required!
         *          'attr'      => array('id+name' => 'username'),
         *      ),
         * ),
         */
    );
    
    /**
     * getModuleInfo is a module required by all modules to tell ProcessWire about them
     * @return array
     */
    public static function getModuleInfo() {
        return array(
            'title' => 'FormHelper',
            'summary' => 'Generate and process forms from page / template fields or given field parameters',
            'version' => '0.0.2',           
        );
    } 
        
    protected function setCfg ($arr, $reset = null) {
        if ($reset === null) {
            $this->cfg = array_replace_recursive($this->cfg, $arr);
        }
        else {
            $this->cfg = $arr;
        }
    }
    
    /**
     * Generate the form object from given fields
     * @return object Generated form
     */
    public function ___createForm (array $cfg = null, $reset = null) {
        // merge or overwrite default config
        if ($cfg !== null)  $this->setCfg($cfg, $reset);

        // create form field / wrapper
        $this->form = $this->setObj($this->cfg['form']);
        
        // Get inputfields from page object or given template
        if ($this->cfg['page'] || $this->cfg['template'])   $this->getFormInputfields();
        
        // create or merge form with given field data array
        if ($this->cfg['fields'] !== null && is_array($this->cfg['fields']))    $this->createFormFields();

        // add submit button
        $this->submitBtn = $this->setObj($this->cfg['submit']);
        $this->form->add($this->submitBtn);
        
        return $this->form;
    }

    /**
     * ToDo: implement method / field positioning ?
     */
    public function formField ($field, $method = 'add', $posRefField = null) {
        $field = $this->prepareField($field);
        $this->form->$method($field);
    }
    
    /**
     * 
     */
    protected function ___prepareField($field) {
        if(in_array($field->name, $this->cfg['skipFields'])) return null;    // remove field
        if ($this->cfg['clearFormValues']) $field->value = null; // set value to empty
        return $field;
    }
    
    /**
     * Generate inputfields from given page object fields
     * @return object Generated field
     */
    protected function getFormInputfields () {
        if ($this->cfg['template'] && !$this->cfg['page']) { 
            $this->cfg['page'] = $this->fakePage($this->cfg['template']);
        }
        foreach ($this->cfg['page']->getInputfields() as $field) {
            $this->formField($field);
        }
    }
    
    /**
     * Generate form fields based on given data array
     * @return object Generated field
     */
    protected function createFormFields() {
        foreach ($this->cfg['fields'] as $formField) {
            // Update form field if exists
            if ($exists = $this->form->get($formField['vars']['name'])) {
                $this->setObjValues($exists, $formField);
            }
            // Doesn't exist? Create and add it to form...
            else {
                $field = $this->setObj($formField);
                $this->formField($field);
            }
        }
    }
    
    /**
     * Rendering the current form
     * @return string Rendered form as html code
     */
    public function ___render() {
        return $this->form->render();
    }
    
    /**
     * Process form data if send
     * @return object Processed form data
     */
    public function ___formProcess() {
        $submit = $this->submitBtn->get('name');
        
        if(!$this->input->post->$submit) return NULL;    // form NOT submitted...

        $processedForm = $this->form->processInput($this->input->post); // form api process form values
            
        if(!$this->form->getErrors()) return $processedForm;    // form processed: OK
        else return false;   // form send with errors
    }
    
    /**
     * Generate a field / form object
     * @param array $arr Needed values to create the object
     * @return object Generated field object
     */
    private function setObj($arr) {
        $obj = $this->modules->get($arr['module']);
        $this->setObjValues($obj, $arr);
        return $obj;
    }

    /**
     * Update form / field variables and values
     * @param object $obj field object by reference
     * @param array $arr field variables/ properties and attributes
     */
    private function setObjValues(&$obj, $arr) {
        if (is_array($arr['vars'])) {
            foreach ($arr['vars'] as $key => $value) {
                $obj->set($key, $value);
            }    
        }
        elseif (is_array($arr['attr'])) {
            foreach ($arr['attr'] as $key => $value) {
                $obj->set($key, $value);
            }    
        }
    }
    
    /**
     * Make fake page and assign needed template
     * @param string $tpl Template to assign
     * @return object Generated fake page to work with
     */
    private function fakePage($tpl) {
        $fakePage = new Page();
        $fakePage->template = $tpl;
        return $fakePage;
    } 
    
    /**
     * jsConfig settings needed by wysiwyg editor
     * @return string Basic JavaScript config
     */
    public function ___jsConfig () {
        $jsConfig = $this->config->js();
        $jsConfig['debug'] = $this->config->debug;                                                          
        $jsConfig['urls'] = array(     
            'root' => $this->config->urls->root,
            'admin' => $this->config->urls->admin,
            'modules' => $this->config->urls->modules,                    
            'core' => $this->config->urls->core,                                
            'files' => $this->config->urls->files,                     
            'templates' => $this->config->urls->templates,                                                   
            'adminTemplates' => $this->config->urls->adminTemplates,             
        );                                                      
        return '<script type="text/javascript">var config = ' . json_encode($jsConfig) . '</script>';       
    }
}

Some features (jquery, jsconfig, ...) missing, but it works with a simple page / template...

My testing template code (also with form field overwrite (for example field username).

<?php

$fh = $modules->get('FormHelper');

$formFields['username'] = array(
            'module'    => 'InputfieldText',
            'vars'      => array('name' => 'username', 'label' => 'Username123', 'required' => true),
            'attr'      => array('id+name' => 'username'),
        );

$fh->createForm(array('template' => 'register', 'fields' => $formFields));

// process form
$process = $fh->formProcess();
if ($process === NULL) {
     echo "Nicht abgeschickt<br /> <br />";
}
elseif ($process == true) {
     echo "Abgeschickt, ohne Fehler<br /> <br />";
}
elseif ($process === false) {
     echo "Abgeschickt, mit Fehlern<br /> <br />";
}

$form = $fh->render();  // returns rendered form 

echo '<html><head>'; 

// jsConfig needed by wysiwyg editors
echo $fh->jsConfig() . "\n"; 

// outpunt needed scripts for inputfield modules, ...
foreach ($config->scripts as $file) { echo "<script type='text/javascript' src='$file'></script>\n"; }
foreach ($config->styles as $file) { echo "<link type='text/css' href='$file' rel='stylesheet' />\n"; } 

echo '</head><body>';
echo $form;    
echo '</body></html>';

Be careful... don't use "$fields" as variable to build the form fields data array. I should change the array key 'fields' again because it lead to use $fields as variable to build the sub array...  :rolleyes:

UPDATE

Latest version also fixed a bug during set field properties / attributes...

  • Like 1

Share this post


Link to post
Share on other sites

Bitbucket FormHelper Repo is online...

dev / unstable !!!

https://bitbucket.org/pwFoo/formhelper/src/8ca0b543d87b5534ac476d2e240466a216d34be6/FormHelper/FormHelper.module?at=master

Sorry, readme file isn't readable online... It's a simple example usage php file.

I paste it here...

<?php
$fh = $modules->get('FormHelper');

//////////////////////
////// EXAMPLES //////
// form based on template object
$fh->createForm($templates->get('myTemplate'));

// form based on page object
$fh->createForm($pages->get('myPage'));

// form based on a page, but clear field values and remove the fields headline, sidebar
$fh->createForm($pages->get('myPage'), array('clearValues' => true, 'skipFields' => array('headline', 'sidebar')));

// Build form from template register and then modifiy username field label...
$formFields['username'] = array(
    'module'    => 'InputfieldText',
    'vars'      => array('name' => 'username', 'label' => 'Username123', 'required' => true),
    'attr'      => array('id+name' => 'username'),
);
$fh->createForm($templates->get('register'), array('fields' => $formFields));

// Create a login form from array data only and change default "Submit" to "Login"
$formSubmit = array('vars' => array('name' => 'submit'), 'attr' => array('value' => 'Login'));
$formFields = array(
    'username' => array(
        'module'    => 'InputfieldText',
        'vars'      => array('name' => 'username', 'label' => 'Username', 'required' => true),
        'attr'      => array('id+name' => 'username'),
    ),
    'password' => array(
        'module'    => 'InputfieldText',
        'vars'      => array('name' => 'password', 'label' => 'Password', 'required' => true, 'type' => 'password'),
        'attr'      => array('id+name' => 'password', 'type' => 'password'),
    ),
);
$fh->createForm($this->formFields, array('submit' => $this->formSubmit));

////// EXAMPLES //////
//////////////////////

// process form
$process = $fh->formProcess();
if ($process === NULL) {
     // form not sent
}
elseif ($process == true) {
     // form sent, without errors... do something
}
elseif ($process === false) {
     // form sent, but with errors! ...
}

$form = $fh->render();  // returns rendered form 

echo '<html><head>'; 

// jsConfig needed by wysiwyg editors
echo $fh->jsConfig() . "\n"; 

// outpunt needed scripts for inputfield modules, ...
foreach ($config->scripts as $file) { echo "<script type='text/javascript' src='$file'></script>\n"; }
foreach ($config->styles as $file) { echo "<link type='text/css' href='$file' rel='stylesheet' />\n"; } 

echo '</head><body>';
echo $form;    
echo '</body></html>';
  • Like 1

Share this post


Link to post
Share on other sites

The above linked version internal adds all fields (field objects and also field array data) with one function.

public function field($field, $method = 'add', $refPosObj = null, $bypass = null)

$field: field object OR array of field information to add (inputfield module and field name required) OR update (also field name required) if exists

$method: add, insertBefore, remove, ... to build the "$form->$method()" call.

$refPosObj: is needed by $method insertAfter or insertBefore. Have to be a field object

$bypass: Skip hookable prepare / validate function (used tro handle "skipFields", or "clearValues") before add to form

So after create the form it should be possible to modify it with a $fh->field(...) call or directly change the form object $fh->form from outside.

This two cases are untested, but forms fine from inside...

Share this post


Link to post
Share on other sites

And again some changes ;)

Some bugs fixed and repo is updated.

At the moment I prefer as parameters to build a form

parameter 1: fields as objects or array data

parameter 2: only module options like "clearValues", "skipFields", ... (but additional field data like change submit button, form attributes or also fields is still possible until now...)

Build the form and then modify could be done in two steps. Here an example.

$fh->createForm($templates->get('register'), array('clearValues' => false, 'jquery' => false));

$modifyFields['username'] = array(
    //'module'    => 'InputfieldText',
    'pos'       => array('method' => 'insertAfter', 'refObj' => $fh->form->get('email')),
    'vars'      => array('name' => 'username', 'label' => 'Username123'),
);
$modifyFields['submit'] = array(
    'vars'      => array('name' => 'submit'),
    'attr' => array('value' => 'Login'),
    );

echo "Before modify: " . $fh->form->get('submit')->value . "<br />";

foreach ($modifyFields as $modifyField) {
    $fh->field($modifyField);
}

echo "After modify: " . $fh->form->get('submit')->value . "<br />";

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...