Friday 31 January 2020

Form with multiple steps php

1. If you want to create a multiple step form you can follow below step , i am using codeigniter as my framwork php , index function is a single function which will handle your request and process your form , $form_process_id,$form_id,$step_id_u,$is_previous_action is the main variable other variable are my custom variable which i am passing , you can assign your variable as per your requirement.

2. fpi short means form process id, multiple if else in index function is for like when you in step1 include only step1 data , if you in step 2 include only step2 data by fetching records from mysql.

3. if you see the screenshot there is a table which contain post_values,post_values_front fields in mysql , post_values fields store form data as serialize at user end and post_values_front store the html which you can be save from your admin panel.

4. $data['main'] in index function just get the in which step you are and fetch accordingly. you have to create a directory stepforms , where step1.php , step2.php.... etc file will be created as per multi form you want to create , Please see below what html they will containstep1.php ...etc. i have included my custom variable also for query to database you can remove those. I commented the $save_step_data in else statement because for front end user update query always fire not new record will be added because from your admin panel step data , html already saved, for admin panel you have to enable those line , because admin side iif fpi found then update if not then insert/save will goes accordinlgy. you can also include js/jquery in step1.php or step2.php etc. you can use below function for any kind of multiple user registration or where you need any kind of multiple form submission.

class MultiStep extends MY_Controller {
    public function index() {
        $search_gstin_id = (int) isset($_GET['sid']) ? trim($this->input->get('sid', TRUE)) 
: trim($this->input->post('sid', TRUE));
      $financial_year = isset($_GET['fy']) ? $this->input->get('fy', TRUE) : $this->input->post('fy', TRUE);
      $form_process_id = (int) $this->input->get('fpi');
      $is_previous_action = $this->input->get('p');
      $form_id = $this->uri->segment(3, 0);
      $step_id_u = $this->uri->segment(4, 1);
      $step_id_p = isset($_POST['step_id']) ? (int) $step_id_u : $step_id_u;
      $this->load->model('AuditCustomForms');
      $total_steps = $this->AuditCustomForms->get_total_form($form_id);
      $form_name_info = $this->AuditCustomForms->get_form_name($form_id);
      if ($step_id_p != '') {
          if ($is_previous_action != '') {
              $field_id = (int) $step_id_p;
          } else {
              $field_id = (int) $step_id_p;
          }
      } else {
          $field_id = $step_id_u;
      }
      $form_info = $this->AuditCustomForms->get_step_from($form_id, $field_id);
      $form_data = $this->AuditCustomForms->get_from_data($form_process_id, $field_id);
      $save_id = '';
      if (!empty($_POST) && is_array($_POST)) {
          $sdata = $this->input->post();
          unset($sdata['step_id']);
          unset($sdata['form_id']);
          if ($this->input->get('isf') == 'yes') {
              if (!empty($form_data)) {
                $save_step_data = array('post_values_front' => serialize($sdata), 'status' => 1,
 'search_gstin_id' => $search_gstin_id, 'gst_financial_year' => $_POST['fy']);
                $save_id = $this->AuditCustomForms->do_update_records('audit_post_values',
 $save_step_data, array('form_process_id' => $form_process_id, 'field_id' => $step_id_u));
              } else {
               //$save_step_data = array('status' => 1, 'form_process_id' => $form_process_id
, 'user_id' => $this->user_id, 'form_id' => $form_id, 'field_id' => $step_id_u,
 'post_values_front' => serialize($sdata), 
'created_date' => $this->today, 'search_gstin_id' => $_POST['sid'], 'gst_financial_year' => $_POST['fy']);
                //$save_id = $this->AuditCustomForms->do_save_records('audit_post_values', $save_step_data);
              }
            $_SESSION['markfront'] = alertmessage($message_type = 'alert-success', 
$message = 'TaxAudit have been saved successfully.');
              $this->session->mark_as_flash('markfront');
              redirect(base_url() . '/dashboard/');
              exit;
           } else {
           if (!empty($form_data)) {
              $save_step_data = array('status' => 1, 'post_values_front' => serialize($sdata),
 'search_gstin_id' => $search_gstin_id, 'gst_financial_year' => $_POST['fy']);
             $save_id = $this->AuditCustomForms->do_update_records('audit_post_values'
, $save_step_data, array('form_process_id' => $form_process_id, 'field_id' => $step_id_u - 1));
           } else {
            //$save_step_data = array('status' => 1, 
'form_process_id' => $form_process_id, 'user_id' => $this->user_id, 'form_id' => $form_id,
'field_id' => $step_id_u, 'post_values_front' => serialize($sdata),
'created_date' => $this->today, 'search_gstin_id' => $_POST['sid'], 'gst_financial_year' => $_POST['fy']);
            //$save_id = $this->AuditCustomForms->do_save_records('audit_post_values', $save_step_data);
           }
          }
        }
        if ($step_id_u == 2) {
        } else if ($step_id_u == 3) {
        } else if ($step_id_u == 4) {
        } else if ($step_id_u == 5) {
        } else if ($step_id_u == 6) {
        } else if ($step_id_u == 7) {
        } else if ($step_id_u == 8) {
        } else if ($step_id_u == 9) {
        } else if ($step_id_u == 10) {
        } else if ($step_id_u == 11) {
        } else if ($step_id_u == 12) {
        } else {
        }
        $data['search_gstin_id'] = $search_gstin_id;
        $data['financial_year'] = $financial_year;
        $data['form_process_id'] = $form_process_id;
        $data['form_info'] = $form_info;
        $data['form_data'] = $form_data;
        $data['form_id'] = $form_id;
        $data['next_step'] = count($form_info) > 0 ? $form_info[0]->field_id : '';
        $data['actual_step_id_p'] = $step_id_p;
        $data['post_id'] = $save_id;
        $data['form_name_info'] = $form_name_info;
        $data['header'] = 'dashboard/header';
        $data['main'] = 'stepforms/' . $form_id . '/' . $form_info[0]->step;
        $data['footer'] = 'front/footer';
        $this->load->vars($data);
        $this->load->view($this->user_dashboard);
    }
}

5. Below is the model which contain function for saving and updating form data ,generateFormToken function will generate a unique fpi for your form. model is just fetching records from mysql database.

class AuditCustomForms extends CI_Model {
    function __construct() {
        parent::__construct();
        $this->load->database();
    }
    function generateFormToken() {
        $query = $this->db->query('SELECT LPAD(FLOOR(RAND()*99999), 5, 0) AS random_num FROM 
        audit_post_values WHERE "random_num" NOT IN (SELECT post_id FROM audit_post_values) LIMIT 1');
        $row = $query->row();
        if (isset($row)) {
            return $row->random_num;
        } else {
            $query = $this->db->query('SELECT LPAD(FLOOR(RAND()*99999), 5, 0) AS random_num');
            $row = $query->row();
            return $row->random_num;
        }
    }
    function get_step_from($form_id, $field_id) {
        $this->db->select('ff.*');
        $this->db->from('audit_form_fields ff');
        $this->db->where('ff.form_id', $form_id);
        $this->db->where('ff.field_id', $field_id);
        $query = $this->db->get();
        return $query->result();
    }
    function do_update_records($table, $data, $where) {
        $this->db->where($where);
        if ($this->db->update($table, $data)) {
            $query_id = $this->db->select('post_id')->where($where)->get($table);
            return $query_id;
        } else {
            return NULL;
        }
    }
    function do_save_records($table, $data) {
        if ($this->db->insert($table, $data)) {
            return $this->db->insert_id();
        } else {
            return NULL;
        }
    }
    function get_from_data($form_process_id, $field_id) {
        $this->db->select('*');
        $this->db->from('audit_post_values pv');
        $this->db->where('pv.form_process_id', $form_process_id);
        $this->db->where('pv.field_id', $field_id);
        $query = $this->db->get();
        if ($query->num_rows() > 0) {
            return $query->result();
        } else {
            return NULL;
        }
    }
}

6. Below is the first step form , either you can include html directly to below view file or if you want to fetch html from database for example you have a admin panel where you manage content , you can also make or use same function for your admin panel which store only html in post_values fields as serialised and them you can use it like below or replace "//your html element , form will go here step 1" by below line , so what ever html you saved from your admin panel it will display that html for step1 , step2.....etc.

$str_template=!empty($form_html['auditforms']) ? html_entity_decode($form_html['auditforms']) : '';
<?php
if (!empty($form_data)) {
    $form_html = unserialize($form_data[0]->post_values);
    $post_values_front = unserialize($form_data[0]->post_values_front);
}
?><section class="section novi-background sec_nw">
    <div class="container">
        <div class="section-sm-41 row justify-content-sm-center align-items-sm-center">
            <div class="card section-34">
                <?php echo form_open(base_url() . 'MultiStep/index/
' . $form_id . '/2/?fpi=' . $form_process_id . '&sid=' . $search_gstin_id . '&fy=' . $financial_year . ''
, array('class' => "", 'autocomplete' => "on", 'id' => 'form1', 'name' => 'form1', 'method' => 'post')); ?>
                <input type="hidden" name="form_id" id="form_id" 
value="<?php echo!empty($form_info) ? $form_info[0]->form_id : ''; ?>"> 
                <input type="hidden" name="step_id" id="step_id" value="<?php echo $next_step; ?>"> 
                <input type="hidden" name="sid" id="sid" value="<?php echo $search_gstin_id; ?>"> 
                <input type="hidden" name="fy" id="fy" value="<?php echo $financial_year; ?>"> 
                //your html element , form will go here step 1
                <input type="submit" class="btn bg-orange btn-flat pull-right" value="Next"/>
                <?php echo form_close(); ?> 
            </div>
        </div>
    </div>
</section>

7. Below is the step2 so previous and next value assign accordingly. you can set previous and next value or step_id, only your html part will be dynamic from mysql.

<section>
    <div class="container profile-edit">
        <div class="section-sm-41 row justify-content-sm-center align-items-sm-center">
            <div class="card section-34">
                <?php echo form_open(base_url() . 'MultiStep/index/
' . $form_id . '/3?fpi=' . $form_process_id . '&sid=' . $search_gstin_id . '&fy=' . $financial_year . ''
, array('class' => "", 'autocomplete' => "on", 
'enctype' => "multipart/form-data", 'id' => 'step1', 'name' => 'step1', 'method' => 'post')); ?>
                <input type="hidden" name="form_id" id="form_id" 
value="<?php echo!empty($form_info) ? $form_info[0]->form_id : ''; ?>"> 
                <input type="hidden" name="step_id" id="step_id" value="<?php echo $next_step; ?>">
                <input type="hidden" name="sid" id="sid" value="<?php echo $search_gstin_id; ?>"> 
                <input type="hidden" name="fy" id="fy" value="<?php echo $financial_year; ?>"> 
                //your html element , form will go here step 2
                <div class="col-offset-10">
                    <a href="<?php echo base_url() . 'MultiStep/index/
' . $form_info[0]->form_id . '/1/?sid=' . $search_gstin_id . 
'&fpi=' . $form_process_id . '&p=' . $actual_step_id_p . '&audit_form_id=' . $form_id . 
'&fy=' . $financial_year; ?>" class="btn bg-orange btn-flat pull-left">Prev</a>
                    <input type="submit" class="btn bg-orange btn-flat pull-right" value="Next"/>
                </div>
                <?php echo form_close(); ?> 
            </div>
        </div>
    </div>
</section>

8.In my project there are 24 steps so that is my last step , may in your case there is less step then mine , if you are making your last step so &isf=yes should be added in rest of step isf will not add to recognise last we are in last request.

<section class="section novi-background sec_tab">
    <div class="container profile-edit">
        <div class="section-sm-41 row justify-content-sm-center align-items-sm-center">
            <div class="card section-34 ">
                <?php echo form_open(base_url() . 'TaxAudit/index/
' . $form_id . '/24/?fpi=' . $form_process_id . '&isf=yes', array('class' => "", 
'autocomplete' => "on", 'id' => 'form1', 'name' => 'form1', 'method' => 'post')); ?>
                <input type="hidden" name="form_id" id="form_id" 
value="<?php echo!empty($form_info) ? $form_info[0]->form_id : ''; ?>"> 
         <input type="hidden" name="step_id" id="step_id" value="<?php echo $next_step; ?>"> 
         <input type="hidden" name="sid" id="sid" value="<?php echo $search_gstin_id; ?>"> 
         <input type="hidden" name="fy" id="fy" value="<?php echo $financial_year; ?>"> 
          //your html element , form will go here step finished
        <div class="col-offset-10">
        <a href="<?php echo base_url() . 'TaxAudit/index/
' . $form_info[0]->form_id . '/23/?sid=' . $search_gstin_id . '&fpi=
' . $form_process_id . '&p=' . $actual_step_id_p.'&
audit_form_id=' . $form_id . '&fy=' . $financial_year; ?>" class="btn bg-orange btn-flat pull-left">Prev</a>
           <input type="submit" class="btn bg-orange btn-flat pull-right" value="Finished"/>
           </div>
           <?php echo form_close(); ?> 
     </div>
     </div>
    </div>
</section>

9. The screenshot will show you the table structure to manange multi step form.


Tuesday 28 January 2020

User roles permission menu treeview

1. If you want to build a user role permission and dynamic side bar menu in your web application using Codeigniter and Mysql , In this senario all menu and submenu will show like a tree using jstree.Below is the js you will required

#link https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css
#https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js

2. Below is the part of html you required to display all menu items (Menu Permission) , you can just copy and paste it in any html or where you want to show that menus for admin panel or user , you can customise accordingly. AdminMenu is the model , you can place this line in any of your view file it will return html of ul, li and if you want not directly placing in view you can call controller function then parse data in view file.

echo this->AdminMenu->get_menu($role_id);

3. Below script goes in your view file or javascript file. showalert_mpop is a javascript function , you can see my other post to check this function it simply alert , display message with setTimeOut.

<script>
    $(function () {
        var tree = $("#treeview2");
        tree.jstree({
            plugins: ["checkbox", 'json_data'],
            core: {
                "themes": {
                    "icons": false,
                    "variant": "large",
                    "multiple": false,
                    "check_callback": true,
                }
            },
            "checkbox": {
                "keep_selected_style": false,
                "two_state": true,
            }
        });
        tree.jstree(true).open_all();
        $('li[data-checkstate="checked"]').each(function () {
            tree.jstree('check_node', $(this));
        });
        tree.jstree(true).close_all();
        $(function () {
            $('#treeview2').on('select_node.jstree Event', function (e, data) {
                var checked_menu_id = '';
                var parent_menu_id = '';
                if (data.node.children.length > 0) {
                    $.each(data.node.children, function (key, value) {
                        checked_menu_id += $("#" + value).attr('name') + ',';
                    }).join(',');
                    parent_menu_id = $("#" + data.node.id).attr('name');
                } else {
                    checked_menu_id = $("#" + data.node.id).attr('name');
                    parent_menu_id = $("#" + data.node.parent).attr('name');
                }
                var rid_c = "";
                $.ajax({
                url: base_url+'Settings/do_save_menu_per',
                type: 'POST',
                dataType: 'json',
                data: {mid: checked_menu_id, rid: rid_c, status: 'checked', 'parent': parent_menu_id},
                beforeSend: function () {
                   $(".faster_ajax_loader").css('display', 'block');
                },
                complete: function () {
                   $(".faster_ajax_loader").css('display', 'none');
                },
                success: function (response) {
                     showalert_mpop(response.msg, 'gobal_msg');
                 }
                });
            });
        });
        $('.minimal').on('click', function(event){
            var is_chk_unch='';
            if(this.checked) {
                 is_chk_unch='y';
            }else{
               is_chk_unch='n';
            }            
            $.ajax({
             url: base_url + 'Settings/do_save_module_per',
             type: 'POST',
             dataType: 'json',
             data: {is_chk: is_chk_unch, id: $(this).prop('id')},
             beforeSend: function () {
                 $(".faster_ajax_loader").css('display', 'block');
             },
             complete: function () {
                 $(".faster_ajax_loader").css('display', 'none');
             },
             success: function (response) {
                    showalert_mpop(response.msg, 'gobal_msg');
             }
            });
        });
   });
</script>

4. Table schema you can view and download from below link and admin module you can also view see link

#https://github.com/boy108zon/User-Roles-Permission-Menu-TreeView/blob/master/table%20structure.txt
https://github.com/boy108zon/User-Roles-Permission-Menu-TreeView/blob/master/AdminMenu.php

5. The screenshot will show you the final output like side bar menu , module and permission with checkbox , you can easily assign permission based on your roles.



Monday 20 January 2020

Encrypt decrypt aes ecb openssl

This class provide a way of Encryption & decrypt GST PHP code helps illustrate how to encryption & decript, to protect sensitive data. Using openssl_encrypt and openssl_decrypt cryptographic functions.

you don't need to intantiate the class object because its funciton are static. you can directly access the methods.certificate_file_path is your cert file path it can be sandbox or production cert files ,you can either generate it or get it from providers.

You can also use below class to generate token for any web application , $filepath will be the path of security certificate (.cer) on your local machine or your server path where you kept the .cer file. If you don't have a .cer file you can just google for it to "How To Generate .Cer File". AES known as Advanced Encryption Standard is a symmetric-key encryption algorithm.

class GSTAPIENC {
    static function test(){
        return 1;
    }
    static function generateappKey ($appkey,$filepath){
        openssl_public_encrypt($appkey, $encrypted, file_get_contents($filepath));
        return base64_encode($encrypted);   
    }
    static function encryptOTP($otp_code,$appkey) {
       return base64_encode(openssl_encrypt($otp_code, "AES-256-ECB", $appkey, OPENSSL_RAW_DATA));
    }
    static function encryptData($data, $key) {
        return base64_encode(openssl_encrypt($data, "AES-256-ECB", $key, OPENSSL_RAW_DATA));
    }
    static function mac256($ent, $key) {
        $res = hash_hmac('sha256', $ent, $key, true); 
        return $res;
    }
    static function decryptData($data, $key) {
        return openssl_decrypt(base64_decode($data), "AES-256-ECB", $key, OPENSSL_RAW_DATA);
    }
    static function decodeJsonResponse($out, $rek, $ek) {
        $apiEK = GSTAPIENC::decryptData($rek, $ek);
        return base64_decode(GSTAPIENC::decryptData($out, $apiEK));
    }
    static function keygen($length = 10) {
        $key = '';
        list($usec, $sec) = explode(' ', microtime());
        mt_srand((float) $sec + ((float) $usec * 100000));
        $inputs = array_merge(range('z', 'a'), range(0, 9), range('A', 'Z'));
        for ($i = 0; $i < $length; $i++) {
            $key .= $inputs{mt_rand(0, 61)};
        }
        return base64_encode($key);
    } 
}

You can use it like below to generate API KEY

$certificate_file_path = "PATH OF YOUR SANDBOX OR PRODUCTION cert file.";
$generated_key = GSTAPIENC::keygen(32);
$appKey = GSTAPIENC::generateappKey(base64_decode($generated_key), $certificate_file_path);

You can also view download source

https://github.com/boy108zon/Encryption-Decription-GST

Wednesday 8 January 2020

Popover jquery content with ajax php

Let say if you have a user listing Or any kind of dynamic listing which is displaying information from database like mysql etc.. , so some time we want information of each users or product to display over a jQuery Popover with tab based. When popover will open it shows tab based information so that more information can be displayed over it.Below is the html link where user can click to get information.

Basically i had a loop of listing where i have to show up jquery popover with tab based so, when user click on button , viewSearchPayer function call and has one argument which can be userid or any thing. You can also take any unique ids or your data array element which is comming unique in Array. popoverId is important so that we can easily destroy or close the popover.

Response from your server side script like PHP etc will be html of tab ul li with user information or as per your requirements you can set accordingly.

<a class='btn btn-xs btn-warning' onclick='viewSearchPayer('EENPS9');'>gtInfo</a>

Below is the javascript function which is called when user click on button which have onclick event.

function viewSearchPayer(id) {
var popoverId = 'clientinfo_' + id;
var elem='Information 
<button type="button" onclick="closePop('+id+')" id="close" class="close">×<button>';
    $.ajax({
        type: 'POST',
        url: 'your_url_here',
        data: {"method": "viewSearchPayer", "id": id},
        dataType: 'json',
        async: true,
        success: function (response) {
            var Result;
            if (response.RESULT == 'SUCCESS') {
                Result = response.data;
            } else {
                Result = response.data;
            }
            $("."+popoverId).popover({
                container: 'body',
                placement: 'top',
                html: true,
                title: elem,
                content: Result
            }).popover('show');
        }
    });
}
Below is the javascript function which is called when user click on close button over popover so that we can close it. popoverId should be unique or you can adjust it according to your need.
function closePop(popoverId) {
     var closepopoverId = 'clientinfo_' + popoverId;
     $("."+closepopoverId).popover('hide');
  }

Below is the simple tab based html markup which you can revert back from your server side language like PHP , In this tab based you can also get dynamic data and display accordingly from database to these tabs.

 <ul class="nav nav-tabs">
<li class="active"><a href="#tab1" data-toggle="tab">Info</a></li>
<li class="tab"><a href="#tab2" data-toggle="tab">Track</a></li>
</ul><div class="tab-content">
<div class="tab-pane active" id="tab1"> 
tab1</div>
<div class="tab-pane" id="tab2">
tab2</div></div>