Html table data validation

Html table data validation

by Ricardo Godinho -
Number of replies: 11

Hello, my plugin auto enrols students from a csv file.As it is now, it auto enrolls, no questions asked. But I want to add an extra step before the enrollment.  I would like to only enroll checkboxed students. And those, would appear in a new table(on a new page), enrolled on the course, after clicking a button. Can a html table validate data as well? Here's my code:

$courseid= required_param('id', PARAM_INT);

$plugin=enrol_get_plugin('manual');

$instance = $DB->get_record('enrol', array('courseid'=>$courseid, 'enrol'=>'manual'), '*', MUST_EXIST);

$fp=fopen('sample.csv','r');
$row=1;
$enrolinfo='';
$totalnumber=0;
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('uploaduserspreview','local_ecoclipaluno'));
$table= new html_table();
$table->head =array(get_string('selection','local_ecoclipaluno'),get_string('username','local_ecoclipaluno'),get_string('firstname','local_ecoclipaluno'),get_string('lastname','local_ecoclipaluno'),get_string('number','local_ecoclipaluno'),get_string('email','local_ecoclipaluno'),get_string('auth','local_ecoclipaluno'),get_string('enrollment','local_ecoclipaluno'),'Curso');
$table->tablealign = 'center';

$table->attributes['class']='generaltable';


fgetcsv($fp,1000,";");
while(($data=fgetcsv($fp,1000,";"))!==FALSE){
$user=$DB->get_record('user',array('username'=>trim($data[0])));

if($user==FALSE){ 
$enrolinfo=get_string('usernotregistered','local_ecoclipaluno');

}
$totalnumber++;

if($user && !$user->deleted){
if(is_enrolled($context,$user)){
$enrolinfo=get_string('alreadyenrolled','local_ecoclipaluno');
//continue;
//echo $user->username."\r\n".get_string('alreadyenrolled','local_ecoclipaluno')."\n";
//$table->data[get_string('enrollment','local_ecoclipaluno')]=get_string('alreadyenrolled','local_ecoclipaluno')."\n";
}
else{
$timestart = time();
$timestart = make_timestamp(date('Y', $timestart), date('m', $timestart), date('d', $timestart), date('h',$timestart), 0,0);
if ($instance->enrolperiod) {
$timeend = $timestart + $instance->enrolperiod;
} else {
$timeend = 0;
}

$plugin->enrol_user($instance, $user->id, 5, $timestart, $timeend);
$enrolinfo=get_string('newenrollment','local_ecoclipaluno');

}

}
$table->data[]= array(html_writer::empty_tag('input',array('type'=>'checkbox','name' =>'xpto','checked'=>'checked')),$data[0],$user->firstname,$user->lastname,array_shift($dataClipNumber),$data[1],$user->auth,$enrolinfo,whatCourse(array_shift($dataClipCourse)));
}
fclose($fp);
echo html_writer::start_tag('form',array('action'=>'/somefile.php','method'=>'post'));
echo html_writer::table($table);
echo html_writer::end_tag('form');

Average of ratings: -
In reply to Ricardo Godinho

Re: Html table data validation

by Ricardo Godinho -

Anyone know if this is possible? Basically the first table would be a preview of possible students to enroll. (without the column of Authentication and Enrollment). And then, only the checked students would appear on the final table,by pressing a button, on a new page. (now with the column of Authentication and Enrollment.)

And of course, enrolled in the course

In reply to Ricardo Godinho

Re: Html table data validation

by Davo Smith -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

The Moodle html_table class doesn't do any validation, as it is designed to output an HTML table, not a form.

If you want to generate a form with validation, then you can use the moodleform class to do that, but then it is hard to also make use of html_table at the same time (you can get around this by outputting table html yourself within the form).

Alternatively, you can just write the validation code yourself - just loop through the submitted values and compare them to the available values you loaded from the CSV.

In reply to Davo Smith

Re: Html table data validation

by Ricardo Godinho -

Hmm,  I'm mimicking my preview table of possible students to enroll. I've removed every $table variable and commented the enrolling code.

 

<form>
<table border=1px solid black>
<tr>
<td>#</td>
<td>Username</td>
<td>Nome</td>
<td>Apelido</td>
<td>Número</td>
<td>Email</td>
<td>Curso</td>
</tr>
<?php

$fp=fopen('sample.csv','r');

fgetcsv($fp,1000,";");
while(($data=fgetcsv($fp,1000,";"))!==FALSE){
$user=$DB->get_record('user',array('username'=>trim($data[0])));
echo '<tr>' .
'<td><input type="checkbox" name="username[]" value="' . $data[0] . '" checked="checked"/></td>' .
'<td>' . $data[0] . '</td><td>' . $user->firstname . '</td>' .
'<td>' . $user->lastname . '</td>' .
'<td>' . array_shift($dataClipNumber) . '</td>' .
'<td>' . $data[1] .'</td>' .
'<td>' . whatCourse(array_shift($dataClipCourse)). '</td>' .
'</tr>';

}
fclose($fp);

$mform= new enroll_form(null);
if($mform->is_cancelled()){
redirect($urltogo);
}
else{
$mform->display();
}

So, in order to validate the checkedmarked data, you mean to put this inside my enroll_form? Still, how will the action buttons know that the checked data is the one to validate?

require_once ($CFG->libdir. '/formslib.php');

class enroll_form extends moodleform{
function definition(){

$mform=& $this->_form;
$this->add_action_buttons();

}
}

In reply to Ricardo Godinho

Re: Html form table data validation

by Ricardo Godinho -

Tottaly lost here. Neither I have a form resembling table with possible enrolling students, neither I have the final table of enrolled students. :S. Outputting html inside the form is proving to be quite daunting( inside $mform->addElement('html','<div' class="qheader">') I suppose, with results that resembles nothing to the form table pic above.

This is part of my script file. Only a small portion of data comes from the csv. The rest comes from Moodle DB itself and some other url extraction parameters methods i've done.

$courseid= required_param('id', PARAM_INT);

$urlcancel = new moodle_url('/course/view.php', array('id'=>$courseid));

$fp=fopen('sample.csv','r');
$row=1;
$enrolinfo='';
$totalnumber=0;


echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('uploaduserspreview','local_ecoclipaluno'));
 
$mform= new enroll_form(null,array('id'=>$courseid));
fgetcsv($fp,1000,";");
while(($data=fgetcsv($fp,1000,";"))!==FALSE){
$user=$DB->get_record('user',array('username'=>trim($data[0])));
echo '<tr>' .
'<td><input type="checkbox" name="username[]" value="' . $data[0] . '" checked="checked"/></td>' .
'<td>' . $data[0] . '</td><td>' . $user->firstname . '</td>' .
'<td>' . $user->lastname . '</td>' .
'<td>' . array_shift($dataClipNumber) . '</td>' .
'<td>' . $data[1] .'</td>' .
'<td>' . whatCourse(array_shift($dataClipCourse)). '</td>' .
'</tr>';
if($mform->is_cancelled()){
redirect($urlcancel);              // which doesn't. Lists me all the unchecked users on URL.
}
else{                                    // Clicking save changes button it enrolls all, not just the checked.
if($user==FALSE){
$enrolinfo=get_string('usernotregistered','local_ecoclipaluno');
//echo $user->username."\r\n".get_string('usernotregistered','local_ecoclipaluno')."\n";
//echo $table->data[4]=get_string('usernotregistered','local_ecoclipaluno')."\n";
}
$totalnumber++;


if($user && !$user->deleted){
if(is_enrolled($context,$user)){
$enrolinfo=get_string('alreadyenrolled','local_ecoclipaluno');
}
else{
$timestart = time();
$timestart = make_timestamp(date('Y', $timestart), date('m', $timestart), date('d', $timestart), date('h',$timestart), 0,0);
if ($instance->enrolperiod) {
$timeend = $timestart + $instance->enrolperiod;
} else {
$timeend = 0;
}

$plugin->enrol_user($instance, $user->id, 5, $timestart, $timeend);
$enrolinfo=get_string('newenrollment','local_ecoclipaluno');
}
}

}

}
fclose($fp);

$mform->display();

And the form as it is currently :

require_once ("$CFG->libdir/formslib.php");

class enroll_form extends moodleform{
function definition(){
global $CFG;
$mform=& $this->_form;
$mform->addElement('hidden','id', $this->_customdata['id']);
$mform->setType('id',PARAM_INT);
$this->add_action_buttons();

}
}
function validation($data, $files){

}

In reply to Ricardo Godinho

Re: Html form table data validation

by Davo Smith -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

As I already stated above, it is hard to get html_table and moodleform classes to work together nicely.

You are far better off generating your own HTML for the form and then process it yourself, without trying to use moodleform.

This means you will have to do the validation yourself (reload the data from the CSV, check it against the data that has been submitted), but you won't be trying to force moodleform to output in a way that it isn't designed to work.

In reply to Davo Smith

Re: Html form table data validation

by Ricardo Godinho -

Ok then. That means that I can't use, for example, the get_string('string', 'pluginname') anymore, if I want to generate html buttons or table headings and such, right?

In reply to Ricardo Godinho

Re: Html form table data validation

by Davo Smith -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

Why can't you use get_string() any more?

As far as I can tell, you are still using everything else from Moodle (including get_string and html_table), the only thing you can't use very easily with tables of data is the moodleform class.

 

In reply to Davo Smith

Re: Html form table data validation

by Ricardo Godinho -

Well, the second picture I posted of a table wasnt a html_table. It was created with html. From that I want to transition to the table on 1st picture i posted( minus the checkboxes and only the enrolled chosen on the 2nd pic).   Since moodleforms is out of the question, buttons have also their fixed name. Unless i'm doing one monumental confusion, which I might... This is what i have now.

<form id="form" method="post" action="somefile.php">
<table border=1px solid black align="center">
<div style="text-align:center">
<input type="submit" id="submitDetails" class="submitDetails" name="submitDetails" value="Continue"/>
<input type="button" value="Cancel" onClick="history.go(-1);return true;">
</div>
<tr>

<td>#</td>
<td>Username</td>   <------    cant call get_string here on these headings.
<td>Nome</td>
<td>Apelido</td>
<td>Número</td>
<td>Email</td>
<td>Curso</td>
</tr>

<?php
require_once('../../config.php');
require_once('../../lib/accesslib.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/enrollib.php');
require_once($CFG->libdir.'/formslib.php');
require_once($CFG->dirroot.'/'.$CFG->admin.'/user/lib.php');
require_once('lib.php');

global $DB;
$PAGE->set_context();
$courseid= required_param('id', PARAM_INT);
$url=new moodle_url('/local/ecoclipaluno/somefile.php',array('course'=>$courseid));
$PAGE->set_url($url);
require_login();
if(isset($_POST['submitDetails']))
{
processCsv();
}

.

.etc.....

$fp=fopen('sample.csv','r');
$row=1;
$enrolinfo='';
$totalnumber=0;
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('uploaduserspreview','local_ecoclipaluno'));

fgetcsv($fp,1000,";");
while(($data=fgetcsv($fp,1000,";"))!==FALSE){
//echo "<tr>"; //this
$user=$DB->get_record('user',array('username'=>trim($data[0])));
echo '<tr>' .
'<td><input type="checkbox" name="username[]" value="' . $data[0] . '" checked="checked"/></td>' .
'<td>' . $data[0] . '</td><td>' . $user->firstname . '</td>' .
'<td>' . $user->lastname . '</td>' .
'<td>' . array_shift($dataClipNumber) . '</td>' .
'<td>' . $data[1] .'</td>' .
'<td>' . whatCourse(array_shift($dataClipCourse)). '</td>' .
'</tr>';
}
fclose($fp);

function processCsv(){
$urltogo = new moodle_url('/local/ecoclipaluno/xpto.php', array('id'=>$courseid));
if($user==FALSE){ // este if parece que ta aqui a mais. mas faz o que interessa
$enrolinfo=get_string('usernotregistered','local_ecoclipaluno');
}
$totalnumber++;
if($user && !$user->deleted){
if(is_enrolled($context,$user)){
$enrolinfo=get_string('alreadyenrolled','local_ecoclipaluno');
else{
$timestart = time();
$timestart = make_timestamp(date('Y', $timestart), date('m', $timestart), date('d', $timestart), date('h',$timestart), 0,0);
if ($instance->enrolperiod) {
$timeend = $timestart + $instance->enrolperiod;
} else {
$timeend = 0;
}
$plugin->enrol_user($instance, $user->id, 5, $timestart, $timeend);
$enrolinfo=get_string('newenrollment','local_ecoclipaluno');

.etc...

?>

</table>
</form>

In reply to Ricardo Godinho

Re: Html form table data validation

by Davo Smith -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

You really shouldn't be outputting anything before you get to the $OUTPUT->header() code - the very first line of you file should be to include 'config.php' after which you can use 'get_string' as much as you want.

I think you are really wanting something like the file I've attached.

In reply to Davo Smith

Re: Html form table data validation

by Ricardo Godinho -

Hi Davo, first of all Thank You.

A couple of things though.

Inserting capability checks, i have one check on my lib.php( which is the item creation on Course Admin block that calls somefile.php). Not sure if this is enough though.

if(!has_capability('moodle/backup:backupcourse',context_course::instance($PAGE->course->id))){
return;
}

The csv file has this structure:   username;email;course1   (course1 is the course's shortname). I don't need it for my plugin, but here at my campus when they want to enroll via file, they use this structure.

array_combine isnt really working for me. Wasn't really showing anything on the table. I changed it back to:

while(($data=fgetcsv($fp,1000,";"))!==FALSE){
//$data = array_combine($fields, $data); // Use the $fields array as the names of the data, to make it easier below ...
$user=$DB->get_record('user',array('username'=>trim($data[0])));      And it shows me the data again.

 

The processcsv is not enrolling. and I get an error(shown at bottom of this post) when clicking the continue button( I commented array_combine as well, same reason as above). I would like to display the enrolled on a new table, similar to the first one, and only then to redirect to the course page.  About cancel button operations...now we are entering the realm of moodleforms again, right? And we talked about that already ^^ , since there is no 

echo html_writer::empty_tag('input', array('type' => 'cancel', 'name' => 'canceldetails', 'value' => get_string('cancel')));

function process_csv($fp, $course) {
global $DB;
$enrolinfo=" ";
$requestedusers = required_param_array('username', PARAM_USERNAME);
//$instance = $DB->get_record('enrol', array('courseid'=>$courseid, 'enrol'=>'manual'), '*', MUST_EXIST);
$course = $DB->get_record('course', array('id'=>$instance->courseid), '*', MUST_EXIST);
//$fields = array('username','email','course1');
while (($data = fgetcsv($fp, 1000, ';')) !== false) {
// $data = array_combine($fields, $data);
   if (in_array($user=$DB->get_record('user',array('username'=>trim($data[0]))), $requestedusers)) {
       if(!$enrol_manual = enrol_get_plugin('manual')) { throw new coding_exception('Can not instantiate       enrol_manual'); }
$timestart = time();
$timestart = make_timestamp(date('Y', $timestart), date('m', $timestart), date('d', $timestart), date('h',$timestart), 0,0);
if ($instance->enrolperiod) {
$timeend = $timestart + $instance->enrolperiod;
} else {
$timeend = 0;
}

$enrolled=$enrol_manual->enrol_user($course->id, $requestedusers, 5, $timestart, $timeend);
$enrolinfo=get_string('newenrollment','local_ecoclipaluno');
// This user from the CSV file was included in the submitted data for the form.

// GET ON AND DO THE ENROLMENT IN $course ...
//echo "Enrolling user: {$data['username']}<br/>";
}
}

fclose($fp);
redirect(new moodle_url('/local/ecoclipaluno/xpto.php',array('id'=>$courseid))); // Whever you want to go once the file has been processed.    xpto.php could be my final display table page.
}

error

In reply to Ricardo Godinho

Re: Html form table data validation

by Ricardo Godinho -

Running the enrollment directly on script runs fine, but inside a method doesn't. Don't know why. I have to give him the $instance instead of $course, or else it complains about db error, not correct value types.

function process_csv($fp,$course) {
global $DB;
$plugin=enrol_get_plugin('manual');
$courseid= required_param('id', PARAM_INT);
//$course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
$instance = $DB->get_record('enrol', array('courseid'=>$courseid, 'enrol'=>'manual'), '*', MUST_EXIST);
//$course = $DB->get_record('course', array('id'=>$instance->courseid), '*', MUST_EXIST);
$requestedusers = required_param_array('username', PARAM_USERNAME);
$fp=fopen('sample.csv','r');
fgetcsv($fp,1000,";");
$fields = array('username','email','course1');
while (($data = fgetcsv($fp, 1000, ';')) !== false) {
$data = array_combine($fields, $data);
if (in_array($data['username'], $requestedusers)) {
$timestart = time();
$timestart = make_timestamp(date('Y', $timestart), date('m', $timestart), date('d', $timestart), date('h',$timestart), 0,0);
if ($instance->enrolperiod) {
$timeend = $timestart + $instance->enrolperiod;
} else {
$timeend = 0;
}
// This user from the CSV file was included in the submitted data for the form.
$plugin->enrol_user($instance,(int)$requestedusers, 5, $timestart, $timeend);
// GET ON AND DO THE ENROLMENT IN $course ...
echo "Enrolling user: {$data['username']}<br/>";   It's correctly printing the checked users only.
}
}

fclose($fp);

redirect(new moodle_url('/course/view.php', array('id'=>$courseid))); // Whever you want to go once the file has been processed.
}