form validation with preg_match - forms

I have created a form which gets user data about the city he leaves. The form stores data in a table called profile. I am using a function which inserts data into profile table. If there are already data, the function just updates the table. If the user does not insert data into city field and press submit, the table continues to keep the previous data, because nothing submitted.
In the form I would like to make a validation so that the user will inserts only a-z or space characters.
I have used the following code for validation:
if( empty($_POST) === false ){
if( empty($errors) === true ){
if( preg_match('/^[a-zA-Z ]+$/', $_POST['city']) ===0 ){
$errors[]='<font color="#963">City must only contains a-z and spaces</font>';
}
}
}
It works! But the problem now is that if the user leave the form empty and press submit the above code enforces him to place data( says: City must only contains a-z and spaces). How can I use the above code to validate the form only if the user enters data. And if not then to continue without any problem.

You can do this without even generating an error. Replace
if( preg_match('/^[a-zA-Z ]+$/', $_POST['city']) ===0 ){
With
$_POST['city'] = preg_replace("&[^a-zA-Z ]&","",$_POST['city']);
This will replace all non-lowercase letters and non-spaces with nothing before it's inserted into the database.
EDIT:
If you'd still like to generate an error, use
if( preg_match("&[^a-zA-Z ]&",$_POST['city']) ){
$errors[]='<font color="#963">City must only contains a-z and spaces</font>';
}
before the preg_replace.

Related

My google sheets function does the job when run from editor but gives different outcome when trigered by Form submit

I have a google form and a sheet that collects the responses which of course always appear at the bottom. I have been using the following script to copy the last response (which is always on the last row) from the Response sheet (Form Responses 2) to row two of another sheet (All Responses). When run by a trigger on Form Submit the script inserts a blank row into All Responses, then the copied values into another row above the blank row. Please can you help and tell me why and how I might change the script so the blank row is not added:
function CopyLastrowformresponse () {
var ss = SpreadsheetApp.getActive();
var AR = ss.getSheetByName("All Responses");
var FR = ss.getSheetByName("Form responses 2");
var FRlastrow = FR.getLastRow();
AR.insertRowBefore(2);
FR.getRange(FRlastrow, 1, FRlastrow, 22).copyTo(AR.getRange("A2"), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
}
A few things could be going on here.
You're getting a number of rows equal to FRlastrow, when I think you only want to be getting 1 row.
Apps Script has buggy behavior with onFormSubmit() triggers, so you may to check duplicate triggers (see this answer).
The script isn't fully exploiting the event object provided by onFormSubmit(). Specifically, rather than getting the last row from one sheet, you could use e.values, which is the same data.
I would change the script to be something like this:
function CopyLastrowformresponse (e) {
if (e.values && e.values[1] != "") { // assuming e.values[1] (the first question) is required
SpreadsheetApp.getActive()
.getSheetByName("All Responses")
.insertRowBefore(2)
.getRange(2, 1, 1, e.values.length)
.setValues([e.values]);
}
}
But, ultimately, if all you want to do is simply reverse the order of the results, then I'd ditch Apps Script altogether and just use the =SORT() function.
=SORT('Form responses 2'!A:V, 'Form responses 2'!A:A, FALSE)

Adding columns to a Web2py table in a form

In my web2py application, in the controller I read from an external DB the names of students I want to take a register for. I loop through the resulting list adding the list elements to a new list.
for student in pupils_query:
attendance_list.insert(counter, [student[0], student[1], student[2], student[3]])
counter += 1
counter = 0
Then for each student I read their attendance codes for the day so far from another table, and append them to attendance_list:
for attendance_code in attendance_result:
attendance_list[counter].append(attendance_code)
Now, I'm going to want to make a form from all this, using a table which will show each students' attendance code in a text input (so they can be updated if wrong), then have a dropdown for input of the current lesson code.
I'm using a FORM and TABLE helper to create the table in the form:
form=FORM(TABLE(*[TR(*rows) for rows in attendance_list]))
but can't seem to be able to add a new 'row' form item with something like:
select = "SELECT("+ main_reg_list +")"
attendance_list[counter].append(select)
where main_reg_list is dictionary of acceptable attendance codes (or of course, any other form input element).
In summary, I'm stuck adding new TDs to a table made with a TABLE helper from a list of lists. I bet I'm not the first person to overcome this problem.
I am still not clear about what you want. I think you want table of student information and in one column you want dropdown. Something similat to following image
Above form is created from following code.
I hope following code will help you:
# controller/default.py
def index():
# Dummy attendance list, list after appending attendance code
attendance_list = [['stud_id_1', 'first_name_1', 'last_name_1', 'attendance_code_1'],
['stud_id_2', 'first_name_2', 'last_name_2', 'attendance_code_2'],
['stud_id_3', 'first_name_3', 'last_name_3', 'attendance_code_5'],
['stud_id_4', 'first_name_4', 'last_name_4', 'attendance_code_4']]
possible_att_code = ['attendance_code_1', 'attendance_code_2', 'attendance_code_3', 'attendance_code_4', 'attendance_code_5']
# initialise form_rows with Table heading
form_rows = [THEAD(TR(TH('ID'), TH('First Name'), TH('Last Name'), TH('Attendence Code')))]
for attendance in attendance_list:
attendance_code_dropdown = _get_dropdown(attendance[0], attendance[3], possible_att_code)
td_list = [TD(attendance[0]), TD(attendance[1]), TD(attendance[2]),
TD(attendance_code_dropdown)]
table_row = TR(td_list, _id='row_' + attendance[0])
form_rows.append(table_row)
# Form submit button
form_rows.append(TR(INPUT(_type='submit')))
form = FORM(TABLE(*form_rows), _name='student_attendance',
_id='student_attendance')
if form.accepts(request, session):
# Write code to update record
pass
return dict(form=form)
def _get_dropdown(stud_id, att_code, possible_att_code):
option_list = []
for pac in possible_att_code:
if pac == att_code:
option_list.append(OPTION(pac, _value=pac, _selected='selected'))
else:
option_list.append(OPTION(pac, _value=pac))
return SELECT(*option_list, _name=stud_id)
<!-- views/default/index.html -->
{{extend 'layout.html'}}
{{=form}}
Are my assumptions correct? or you want any thing else? Comment if didn't understood code.

Finding bad words from large list of email addressess using PHP -Mongodb

I have large list of email addressses from a file. It comes around 1 million email ids. I have list of bad words like spam,junk etc, it consist of 20,000+ bad words.
I need to validate email ids. If bad words is present any where in email id it will be marked as invalid.
For example;
testspam#gmail.com - invalid
newuser#desspam.com - invalid
I would like to know which will be fastest comparison method as array looping will take time.
I tried following methods
//$keyword_list- array of bad words;
//$check_key- the email id which need to validate
$arrays = array_chunk($keyword_list, 2000);
for($i=0;$i<count($arrays);$i++)
{
if (preg_match('/'.implode('|', $arrays[$i]).'/', $check_key, $matches)){
return 1;
}
}
The above method is taking more time when comparing 1 million data.
Next we tried with the following code and this also takes more time
//$contain = bad words separated by '|'
// $str - the email id which need to validate
if(stripos($contain,"|") !== false)
{
$s = preg_split('/[|]+/i',$contain);
$len = sizeof($s);
for($i=0;$i < $len;$i++)
{
if(stripos($str,$s[$i]) !== false)
{
return(true);
}
}
}
if(stripos($str,$contain) !== false)
{
return(true);
}
return(false);
Finally I had tried Mongodb Text Search. It works fast with the following issues
If 'Hell' is the word in my bad list and my email id is like
head#e-hellinglysussex.sch.uk, then the Mongodb Text Search wont matches it.
Here is the code I used;
$ret = $db->command( array("text" =>$section, "search" => $keyword_string, "limit"=>$cnt_finalnonmatch));
where $section = Collection name,
$keyword_string = Comparing keywords string separated by space, for eg "Hell Spam Junk" etc,
$cnt_finalnonmatch = total number of comparing email ids
Please help me to solve this issue.
I am not entirely sure, but I suspect that the problem is that 'Hell' is not equal to 'hell' when you search for text since mongodb is case sensitive.
The solution should be to force all the strings and word to be lowercase (or uppercase)
We have used Mongodb 'like' to solve this issue;
$keywords = $key['keyword']; // Keywords need to compare
$regexObj = new MongoRegex("/".$keywords."/i"); // MongoRegex function declration
$where = array($section => $regexObj); // $section is the collection name
$resultset = $info->find($where);

On a HTML Edit form, what is a good approach to have both reset and remember the posted values features?

I have a form which has both server side and client side validation.
It is an edit form, so the original user values are originally pre-populated.
e.g. The original pre-populated values are:
username = yeo
surname = yang
phonenumber = 11-12345
Now, the user edits to the below and submits.
e.g. The edited submitted values are:
username = yeoNew
surname = yangNew
phonenumber = 12-1111
This gets submitted to the serverside and fails the serverside validation because the phonenumber starting with 12 is not allowed.
Anyway, so the form is displayed back to the user as
e.g. The redisplayed form values are:
username = yeoNew
surname = yangNew
phonenumber = 12-1111
This is because my form allows the user to remember their submitted values.
At this stage, I'd like to allow the user to have the ability to reset the form values to the original values using clientside javascript. This is like a reset feature.
e.g. The reset button will restore the form values to:
username = yeo
surname = yang
phonenumber = 11-12345
The reason for this reset feature is that I want the user to have the option to edit the phonenumber again from the original values.
My question is:
What is a good way to keep track of the original values within the HTML so that I can restore it with javascript?
I'm thinking a new attribute called orig='' within the form elements which will store this value.
Is that a good idea?
Any other approaches?
thanks
I would use the HTML5 local storage.
See http://www.w3schools.com/html/html5_webstorage.asp
Using jquery I would do it this way:
<script type="text/javascript">
function load() {
if (localStorage["username"]) {
$('#username').val(localStorage["username"]);
}
if (localStorage["surname"]) {
$('#surname').val(localStorage["surname"]);
}
if (localStorage["phone"]) {
$('#phone').val(localStorage["phone"]);
}
}
function save() {
localStorage["username"] = $('#username ').val();
localStorage["surname"] = $('#surname').val();
localStorage["phone"] = $('#phone').val();
}
</script>

How to populate zend form field using session?

I am using sessions to populate a multi select box with options in my Zend application.
The user selects one or more options and fills in other fields on the form and then submits. If the user didn't select all of the options in the multi select then the form is displayed again but the multi select only has the options that the user did not select the last time. This process goes on until there are no more options from the multi select left to process.
Here is the code I use to get rid of the options that have already been processed so that they are not used to populate the multi select box:
if($form_successful){
// TODO remove $post['keyword_names'] (i.e. already processed) from $keyword_names (that come from $_SESSION)
$keyword_names = array_diff($keyword_names, $post['keyword_names']);
print_r($keyword_names);
if(is_array($keyword_names) && !empty($keyword_names)){
// save updated $keyword_names into $_SESSION['workflow1']
$session = new Zend_Session_Namespace('workflow1');
$session->keyword_names = $keyword_names;
// set flag to false so that we display form again
$form_successful = false;
}else{ // all keywords have been assigned
// go to next step
$this->_redirect('/workflow-1/step-'.($step+1).'/');
}
}
print_r($keyword_names); displays the correct options, however when the form is loaded when the user submits, the multi select displays the options that were there from the begining ie the options the user has just selected and submitted are not being taken out of the multi select, it is only when the user submits the form again then the multi select box updates.
Appreciate the help.
Solved the issue by making use of URL parameters. Here is the code (might differ a lot from what I posted first because some big changes were made):
// after successful form submission
if($form_successful){
// remove $post['keyword_names'] (i.e. already processed) from $keyword_names (that come from $_SESSION)
$keyword_names = array_diff($keyword_names, $post['keyword_names']);
// save remaining $keyword_names into $_SESSION['workflow1']
$session = new Zend_Session_Namespace('workflow1');
$session->keyword_names = $keyword_names;
if(is_array($keyword_names) && !empty($keyword_names)){
// redirect to the same step again - to ensure that the form will reflect (in select lists) newly created AdGroup and/or Campaign
// GET parameteres ($params_array) provide a way to remember user's choice
$params_array = array();
if(!empty($post['match_type_id'])){
$params_array['match_type_id'] = $post['match_type_id'];
}
if(!empty($post['with_permutations'])){
$params_array['with_permutations'] = $post['with_permutations'];
}
if(!empty($ad_group_id)){
$params_array['ad_group_id'] = $ad_group_id;
}
$this_step_url = UrlUtils::assemble('', $this->getRequest()->getActionName(), $this->getRequest()->getControllerName(), $this->getRequest()->getModuleName(), $params_array);
$this->_redirect($this_step_url);
}else{ // all keywords have been assigned
// go to next step
$this->_redirect('/workflow-1/step-'.($step+1).'/');
}
}
So you don't have any code about Zend_Form object here. How do you populate the form element? If you post your class code which extends Zend_Form (or any other code dials with your form) then I may help. But in any case you can populate your multiselectbox with setMultiOptions() method or addMultiOption() for each item in multiselectbox.