<?PHP
/**
 * lib.php - Library of functions and constants for module Register
 * 
 * Modified by Lorenzo Nicora <fad@nicus.it>
 * 
 * @package Register
 * @version $Id: lib.php,v 1.2 2007-07-27 10:59:27 nicus Exp $;
 * @author Domenico Pontari <blueagle@tim.it>
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @link http://moodle.org/mod/newmodule_template.zip here you can download the template
 */

/**
 * REGISTER_DEFAULT_SESSION_TIMEOUT
 *
 * HTTP is a stateless protocol, so you cannot calculate connection time (delay, elapse, duration, ecc...).
 * You can only see requests to an HTTP server, but you can set a timeout so that if the user doesn't request
 * any page until timeout, the activity module breaks your session.
 * Each Register instance has a sessiontimeout value (in minutes). 
 * This value may be set different from (usually less than) Moodle Session Timeout. A lower value 
 * will to reduce overestimating of online sessions.
 * This constant define default value
 *  
 * @see funtion register_insert_session to know how sessiontimeout influence
 * session duration calculation when toleranceevaluation DB field is turned off
 * @link register_insert_session
 */
define("REGISTER_DEFAULT_SESSION_TIMEOUT", 30);

/**
 * REGISTER_DEFAULT_DAYS_CERTIFICABLE
 *
 * When you use the register also to certificate offline amount of hours the user studed.
 * Each Register instance has a dayscertificable value, determining how many days in the
 * past you can date your certification.
 * You can turn off the offline certification in the register activity form mod.html 
 * Default value is defined by this constants
 *
 */
define("REGISTER_DEFAULT_DAYS_CERTIFICABLE",3);


/**
 * REGISTER_STEP_FOR_CALC
 *
 * When you want recalc all sessions, the query asks for a limited number of records
 * so that runtime memory in PHP doesn't go in overflow
 * 
 * @see funcion register_build_session and register_recalc_all_logs to know how all sessions
 * are calculated
 * @link register_build_session,register_recalc_all_logs
 */
define("REGISTER_STEP_FOR_CALC",100);


/**
 * REGISTER_MINIMUM_LOGS_FOR_PAGE
 *
 * When you want recalc all sessions, if there are many logs the web page will go in
 * timeout for the browser. So there I set a threshold: when logs go over it I redirect to
 * the next page.
 * 
 * @see funcion register_build_session and register_recalc_all_logs to know how all sessions
 * are calculated
 * @link register_build_session,register_recalc_all_logs
 */
define("REGISTER_MINIMUM_LOGS_FOR_PAGE",7000);

/**
 * REGISTER_SQL_AGGREGATION
 * 
 * Define which implemetation of register_calc_delay function to use.
 * If true uses SQL SELECT aggragation, otherwhise uses PHP aggregation
 * 
 * @see function register_calc_delay_sql and register_calc_delay_php for different implementations
 * @link register_calc_delay,register_calc_delay_sql,register_calc_delay_php
 */
 define("REGISTER_SQL_AGGREGATION", true);

/**
 * ADD A NEW REGISTER INSTANCE
 *
 * Given an object containing all the necessary data, 
 * (defined by the form in mod.html) this function 
 * will create a new instance and return the id number 
 * of the new instance.
 * @param mixed $register register object
 * @return binary true if DB operation succeeded
 */
function register_add_instance($register) {
    $register->timemodified = time();
    
    return insert_record("register", $register);
}


/**
 * UPDATE A REGISTER INSTANCE
 *
 * Given an object containing all the necessary data, 
 * (defined by the form in mod.html) this function 
 * will update an existing instance with new data.
 * @param mixed $register register object
 * @return binary true if DB operation succeeded
 */
function register_update_instance($register) {

    $register->timemodified = time();
    $register->id = $register->instance;
    return update_record("register", $register);
}

/**
 * DELETE A REGISTER INSTANCE
 *
 * Given an ID of an instance of this module, 
 * this function will permanently delete the instance 
 * and any data that depends on it.  
 * @param int $id ID of an instance of this module
 * @return binary true if DB operation succeeded
 */
function register_delete_instance($id) {
    if (! $register = get_record("register", "id", "$id")) {
        return false;
    }

    $result = true;

    if (! delete_records("register_logs", "register", "$register->id")) { 
    	return false;
    }

    if (! delete_records("register", "id", "$register->id")) {
        $result = false;
    }

    return $result;
}

/**
 * GENERAL USER INFO ABOUT THIS ACTIVITY
 *
 * Return a small object with summary information about what a 
 * user has done with a given particular instance of this module
 * Used for user activity reports.
 * $return->time = the time they did it
 * $return->info = a short text description
 */
function register_user_outline($course, $user, $mod, $register) {

	$return = NULL;
    $online = 0;
    $offline = 0;
    register_calc_delay ($register, $user->id, $online, $offline);
    $total = $online;
    if ($register -> offlinesessions) { 
    	$total += $offline;
    }

    $return->info = print_string ("info", "register") . $total;
    $return->time = time();
    
    return $return;
}

/**
 * DETAILED USER INFO ABOUT THIS ACTIVITY
 *
 * Print a detailed representation of what a  user has done with 
 * a given particular instance of this module, for user activity reports.
 * For this activity type is unuseful: users don't do anything in particular!
 */
function register_user_complete($course, $user, $mod, $register) {

    return true;
}

/**
 * RECENT ACTIVITY ABOUT THE USER
 *
 * Given a course and a time, this module should find recent activity 
 * that has occurred in register activities and print it out. 
 * Return true if there was output, or false is there was none.
 * For this activity type is unuseful: users don't do anything in particular!
 */
function register_print_recent_activity($course, $isteacher, $timestart) {

    return false;  //  True if anything was printed, otherwise false 
}

/**
 * CRON FUNCTION
 *
 * Function to be run periodically according to the moodle cron
 * This function searches for things that need to be done, such 
 * as sending out mail, toggling flags etc ... 
 * No tasks for this activity.
 */
function register_cron () {

    return true;
}

/**
 * GRADES FUNCTION
 *
 * Must return an array of grades for a given instance of this module, 
 * indexed by user.  It also returns a maximum allowed grade.
 *
 *    $return->grades = array of grades;
 *    $return->maxgrade = maximum allowed grade;
 *
 *    return $return;
 *
 * Nothing to do for this module.
 */
function register_grades($registerid) {

   return NULL;
}

/**
 * GET PARTICIPANTS OF REGISTER
 *
 * Must return an array of user records (all data) who are participants
 * for a given instance of register. Must include every user involved
 * in the instance, independient of his role (student, teacher, admin...)
 * See other modules as example.
 * 
 * TODO this should actually be changed, as it returns only users having calculated session in the register
 */
function register_get_participants($registerid) {
//    global $CFG;
//    
//	$sql_str = "SELECT DISTINCT u.*"
//		. " FROM {$CFG->prefix}user u, {$CFG->prefix}register_logs a"
//		. " WHERE a.register = '$registerid' AND u.id = a.userid";
//		
//	return get_records_sql($sql_str);

	$register = get_record("register", "id", $registerid);    
	return register_get_tracked_users($register);
}

/**
 * This function returns if a scale is being used by one register
 * it it has support for grading and scales. Commented code should be
 * modified if necessary. See forum, glossary or journal modules
 * as reference.
 */
function register_scale_used ($registerid,$scaleid) {
   
    return false;
}

//////////////////////////////////////////////////////////////////////////////////////
/// Any other register functions go here.  Each of them must have a name that 
/// starts with register_

/**
 * Retrieve session for a given register and (optionally for a given user)
 * @param $register Register instance
 * @param $userid User ID to filter logs with, if == 0 use no user filtering (=0)
 * @param $online if != '' filter for online == $online
 * @param $sortby SQL sort clause (es. 'login DESC') (='')
 * @return array register_logs instances
 */
function register_get_sessions($register, $userid=0,$online='',$sortby='') {
    
    $sql_str = 'register = ' . $register->id;
    if ( $userid != 0 ) {
    	$sql_str = $sql_str. ' AND userid = ' . $userid;
    }
    if ( $online === 0 || $online === 1 ) { 
    	$sql_str = $sql_str . ' AND online = ' . $online;
    }
    	    	
    $sessions = get_records_select("register_logs", $sql_str, $sortby);    
    return $sessions;
}

/**
 * Get the Course instance the Register is in
 */
function register_get_course($register) {
    $thiscourse = get_record("course", "id", $register->course);
    return $thiscourse;
}


/**
 * Returns Users tracked by Register in a given Course
 * Includes all Users with 'mod/register:tracked' in Course context
 * @param $register Register object 
 * @param $courseid ID of the Curse
 * @param $fields fields list
 * @param $sort sort clause
 */
function register_get_tracked_users_in_course($register, $courseid, $fields='u.id, u.username, u.lastname, u.firstname', $sort='u.lastname') {
	global $CFG;
	
	if (!$fields) {
		$fields='u.id, u.username, u.lastname, u.firstname';	
	}
	
	// Get course Context
	$context = get_context_instance(CONTEXT_COURSE, $courseid);
	$users = get_users_by_capability($context, 'mod/register:tracked', $fields, $sort );
	
	return $users;							
}

/**
 * Comparision function, usable with usort(), ordering user objects by lastname (then firstname and id)
 * Both user object must contains lastname, firstname and id properties
 */
function register_compare_users_by_lastname($user1, $user2) {
	if ( $user1 == $user2 ) {
		return 0;
	}
	$result = strcasecmp($user1->lastname, $user2->lastname);
	if ( $result != 0 ) {
		return $result;
	}
	$result =  strcasecmp($user1->firstname, $user2->firstname);
	if ( $result != 0 ) {
		return $result;
	}
	return strcasecmp($user1->id, $user2->id);
}

/**
 * Comparision function, usable with usort(), ordering user objects by id
 * Both user object must contain id property
 */
function register_compare_users_by_id($user1, $user2) {
	if ( $user1 == $user2 ) {
		return 0;
	}
	return  strcasecmp($user1->id, $user2->id);
}


/**
 * Returns all users the Register instance tracks
 * It includes all tracked users of the Course the Register is in.
 * If type='category' also include 'students' of other courses in the same Category.
 * User are sorted using a custom comparator function
 * @param $register instance of register
 * @param $fields field list
 * @param $sort_function comparator function to use for sorting users
 */
function register_get_tracked_users ($register, $fields='u.id, u.username, u.lastname, u.firstname', $sort_function ='register_compare_users_by_lastname') {
	
    $students = array();
    
    if (!$sort_function) {
    	$sort_function = 'register_compare_users_by_lastname';
    }
	
    // If type is 'normal' or 'metacourse' tracks all users in this course
    if ($register->type != 'category') {
//        return get_course_students ($register -> course,"u.lastname");
		$students = register_get_tracked_users_in_course($register, $register->course, $fields );
    } 
	// If type='category' retrieve tracked users in all courses of the same category    
    else {    
	    $thiscourse = register_get_course ($register);
	    $courses = get_courses ($thiscourse->category);
	    if (!is_array($courses)) {
	    	return false;
	    }
	    foreach ($courses as $course) {
	        // $newstudents = get_course_students ($course,"u.lastname");
			$newstudents = register_get_tracked_users_in_course($register, $course->id, $fields);
	        if (!is_array($newstudents)) { 
	        	continue;
	        }
	        // Adds each newstudent not already in $students
	        foreach ($newstudents as $newstudent) {
	        	$found=false;
	            foreach($students as $student) {
	            	if ( $student->id == $newstudent->id ) {
	            		$found=true;
	            		break;	
	            	}
	            }
	            if (!$found) { 
	            	$students[] = $newstudent;
	            }
	        }
	    }
    }

    // Sort using custom comparator function
	usort($students, $sort_function);
	
    return $students;
}

/**
 * Build SQL only for this course or for all courses in the category
 *
 * BEHAVIOR CHANGE
 * If Course is a Metacourse, the query selects all courses in  the metacourse
 * (not Category, as in the previous version) 
 * @param mixed $register the register instance object
 * @return string SQL string that you should concatenate after WHERE statement for
 * your query.
 */
function register_sqlforcourse ($register) {

	// If not a metacourse filer specified course
	if ($register->type == 'normal') 
    	return "l.course=$register->course";

    $thiscourse = register_get_course($register);

	if ($register->type == 'meta') {
        $courses = get_courses_in_metacourse($register -> course);
	}
	if ($register->type == 'category') {
        $courses = get_courses($thiscourse->category);
	}

    $sql_str = "(";

    // always add register course itself
    $sql_str .= "l.course='$thiscourse->id'";
    // add other courses
    foreach ($courses as $course) {
        if ( $course->id != $thiscourse->id ) { 
          $sql_str .= " OR l.course='$course->id'";
        }
    }
    $sql_str .= ")";
    return $sql_str;
}

/**
 * It evaluates if a session is opened by user and it returns login and logout time
 *
 * @param mixed $register the register instance object
 * @param int $userid the user ID in user table
 * @param int $login parameter passed by reference, it indicates the login time
 * of the current session (if it's open)
 * @param int $logout the register instance object, it is always equal to the
 * current timer: function time (). Inspite of register_insert_session
 * {@link register_insert_session} I don't add to the last log time value also the
 * the timeout value because I suppose that the user is still log on and it's folish
 * set a logout time value in the future: time() + $wait.
 * @param int $wait = REGISTER_SESSION_TIMEOUT by default. It indicates the timeout
 * for the sessions: if the last log of $userid is in the interval between current time
 * less timeout and the current time, it'll mean that there aren't open sessions.
 * @return bool true if there is a session open, false otherwise
 * @see REGISTER_SESSION_TIMEOUT for the philosophy about timeout sessions
 * @uses register_sqlforcourse to select which
 * @link REGISTER_SESSION_TIMEOUT,register_sqlforcourse
 */
function register_user_current_session ($register, $userid ,&$login, &$logout) {
    $logout = time();
    $wait = $register->sessiontimeout;
    if ($login == 0) {
        $sql_str = register_sqlforcourse($register) . ' AND l.userid=' . $userid;
        $countlogs = 0;
        $logs = get_logs($sql_str,'l.time DESC','','',$countlogs);

        if (!is_array ($logs)) { 
        	return false;
        }
        foreach ($logs as $log) {
            if ($login == 0) {
                if ((time() - $log->time) > $wait * 60) { 
                	return false;
                }
                $login = $log->time;
            }
            $delay = $login - ($log->time);
            if ($delay > $wait * 60) { 
            	break;
            }
            $login = $log->time;
        }
    }
    return true;
}

/**
 * It creates sessions from activities hits in log table
 *
 * This is the heart of Register module. This function can calculate the logs of a user
 * and build a session record for register_logs table. It can start from a particular
 * log and exit from while statement when is reached {@link REGISTER_MINIMUM_LOGS_FOR_PAGE
 * REGISTER_MINIMUM_LOGS_FOR_PAGE} limit.
 * It skips log entries containing the work "error" in action field. This avoid accounting log 
 * entries such as "login error" or "forum mail error".
 * @param mixed $register the register instance object
 * @param int $userid the user ID in user table
 * @param bool $display you can calculate logs in silent mode (no echo statements)
 * or you can display something to report the progress of the operations.
 * @param string $sql_log logs that you want to filter. For example you can use {@link register_sqlforcourse register_sqlforcourse}
 * to create the filter.
 * @param int $first_log the log used to start. Useful when you want calculate the logs in
 * more than one web page as in {@link register_recalc_all_logs register_recalc_all_logs}
 * @param int $threshold this is a limit of logs, if you go over the function will exit. Useful
 * to avoid timeout browser or time limit for PHP pages. By default there is no threhold (= 0).
 * @param int $step how many records are loaded by the query in get_logs statement
 * @see  register_recalc_all_logs,register_calc_log in which this function is used.
 * @link register_recalc_all_logs,register_calc_log,REGISTER_SESSION_TIMEOUT,get_logs
 */
function register_build_session ($register, $userid, $display, $sql_log, $first_log = 0, $threshold = 0, $order = "l.time ASC", $step = REGISTER_STEP_FOR_CALC) {

    set_time_limit (0);

    if ($display) {
        //print name and surname of the user of whom you want calculate logs
        echo '<p align="center">';
        // $userdata = get_user_info_from_db ("id", $userid);
		$userdata = get_complete_user_data("id", $userid );
        echo "$userdata->firstname $userdata->lastname<br /><br />";
    }
    
    //totalcount is passed by reference
    $totalcount = 0;
    $logs = get_logs($sql_log ,$order ,$first_log ,$step ,$totalcount);

    if (!is_array ($logs)) {
    	return;
    }
    
    // this variable count how many log's records you have processed, if they are
    // more than $threshold the function will exit
    $current_log = 0;

	// Get session timeout from Register
	$wait = $register->sessiontimeout;

    while (is_array ($logs)) {
        foreach ($logs as $log) {
          // Skip log entry if log->action contains the 'error' word
          if ( stristr($log->action, 'error') === FALSE ) {
                         
             if (!isset($login)) {
                 // for the first time $login is not setted so the first log is also
                 // the first $login
                 $login = $log->time;
                 $last_hit = $log->time;
             }
             $delay = $log->time - $last_hit;
             if ($delay > $wait * 60) {
                 // the difference between the last log and the current log is more than
                 // the timeout Register session value so that we have found a session!
                 register_insert_session ($register->id, $userid, $login, $last_hit, $register->toleranceevaluation, true, $wait);
                 $login = $log->time;
                 if (($threshold >0) && ($current_log > $threshold)) {
                     // if we have calculated enough logs for this page, we'll exit...
                     $end = $current_log + $first_log;
                     if ($display) {
                         echo get_string ("lastcalc", "register"). $end . "<br /></p>";
                         flush(); 
                     }
                     return $end;
                 }
             }
             // now the current log became the previous log for the next cycle
             $last_hit = $log->time;            
          }
          ++$current_log;
        }
        // we have finished all logs for this query, but we aren't enough for this
        // page so we want other new logs
        $end = $current_log + $first_log;
        if ($display) {
            echo get_string ("lastcalc", "register") . $end . "<br />";
            flush(); 
        }
        $logs = get_logs ($sql_log ,$order ,$end ,$step ,$totalcount);
    }
    
    // we have finished all logs for this user, so if there aren't sessions opened
    // we insert also this last session
    $curr_login = NULL;
    $curr_logout = NULL;
    if (!register_user_current_session($register, $userid, $curr_login, $curr_logout)) {
        register_insert_session ($register->id, $userid, $login, $last_hit, $register->toleranceevaluation, true, $wait);
    }
    
    if ($display) { 
    	echo "</p>";
    }
    return 0;
}

/**
 * Calculate aggregate values of offline session for each course.
 * Applicable only to register in metacourse (otherwhise it returns a single value
 * == total offline time).
 * Depending on REGISTER_SQL_AGGREGATION it delegates to PHP or SQL function implementation
 * (register_calc_offline_courses_php and register_calc_offline_courses_sql)
 * 
 * @return array array of int, containing offline times per course, keyed by courseid
 * 
 * @link register_calc_offline_courses_php PHP implementation
 * @link register_calc_offline_courses_sql SQL implementation
 */
function register_calc_offline_courses($register, $userid) {
	if ( REGISTER_SQL_AGGREGATION ) {
		return register_calc_offline_courses_sql($register, $userid);
	}
	else {
		return register_calc_offline_courses_php($register, $userid);
	}	
}

/**
 * Calculate aggregate values of offline session for each course.
 * It uses a simple Query to retrieve register_logs records and calculates aggregates
 * programmatically
 * 
 * @return array array of int, containing offline times per course, keyed by courseid
 */
function register_calc_offline_courses_php($register, $userid) {
    // Gets all register_logs records of user (and register), for offline session
    $sessions = register_get_sessions($register, $userid, 0);

    // Calculate total time for each courseid
    $offline_courses = array();
    if ( $sessions ) {
	    foreach ($sessions as $session) {
	    	$courseid = $session->refcourse;
	    	// Initialize unfound courses elements
	    	if ( !isset( $offline_courses[$courseid] ) ) {
	    		$offline_courses[$courseid] = 0;
	    	}
	    	// Add time to course
	    	$offline_courses[$courseid] += $session->logout - $session->login;
	    } 
    } 
    
    return $offline_courses;   
}

/**
 * Calculate aggregate values of offline session for each course.
 * Calculate sums via SQL aggregate query
 * 
 * @return array array of int, containing offline times per course, keyed by courseid
 */
function register_calc_offline_courses_sql($register, $userid) {
    global $CFG;

	$sql_str = "SELECT refcourse, sum(logout - login) AS delay" 
		. " FROM {$CFG->prefix}register_logs "
		. " WHERE register = $register->id AND userid = $userid AND online = 0 "
		. " GROUP BY refcourse";

    $offline_aggregates = get_records_sql($sql_str);

	// Put results in an associative array
    $offline_courses = array();		
	if ( $offline_aggregates ) {
		foreach ( $offline_aggregates as $course_aggregate ) {
			$offline_courses[$course_aggregate->refcourse] = $course_aggregate->delay;
		}
	}    

    return $offline_courses;
}


/**
 * Calculate aggregated values of online and offline sessions
 *
 * Depending on REGISTER_SQL_AGGREGATION value, delegates calculation
 * to register_calc_delay_sql (==true) or register_calc_delay_php 
 * @param int $online it's passed by reference and it returns the total value of
 * online sessions
 * @param int $offline it's passed by reference and it returns the total value of
 * offline sessions
 */
function register_calc_delay ($register, $userid, &$online, &$offline) {
	if ( REGISTER_SQL_AGGREGATION ) {
		return register_calc_delay_sql($register, $userid, $online, $offline);
	} else {
		return register_calc_delay_php($register, $userid, $online, $offline);
	}	
}

/**
 * Implementation of calculation of aggregated values of online and offline sessions
 * using PHP to calculate total values.
 * register_calc_delay function calls this one if REGISTER_SQL_AGGREGATION == false
 * 
 * @param int $online it's passed by reference and it returns the total value of
 * online sessions
 * @param int $offline it's passed by reference and it returns the total value of
 * offline sessions
 */
function register_calc_delay_php ($register, $userid, &$online, &$offline) {
	$sessions = register_get_sessions($register,$userid,'','logout DESC');

    $online = 0;
    $offline = 0;
    $alogin = 0;
    $alogout = 0;
    if (register_user_current_session ($register, $userid ,$alogin, $alogout) ) { 
    	$online = $alogout - $alogin;
    }
    if (!is_array($sessions) ) { 
    	return;
    }
    foreach ($sessions as $session) {
         if ($session->online) {
         	$online += $session->logout - $session->login;
         } else { 
         	$offline += $session->logout - $session->login;
         }
    }
    return;
}

/**
 * Implementation of calculation of aggregated values of online and offline sessions
 * using SQL aggregate query to calculate total values.
 * register_calc_delay function calls this one if REGISTER_SQL_AGGREGATION == true
 * 
 * @param int $online it's passed by reference and it returns the total value of
 * online sessions
 * @param int $offline it's passed by reference and it returns the total value of
 * offline sessions
 */
function register_calc_delay_sql ($register, $userid, &$online, &$offline) {
    global $CFG;

	$sql_str = "SELECT online, sum(logout - login) AS delay"
		. " FROM {$CFG->prefix}register_logs"
		. " WHERE register = $register->id AND userid = $userid "
		. " GROUP BY online";

    $sessions = get_records_sql($sql_str);
    
    $online = 0;
    $offline = 0;
    $alogin = 0;
    $alogout = 0;
    if (register_user_current_session ($register, $userid ,$alogin, $alogout) ) {
    	$online = $alogout - $alogin;
    }
    if (!is_array ($sessions) ) { 
    	return;
    }
    foreach ($sessions as $session) {
         if ($session->online) { 
         	$online += $session->delay;
         } else { 
         	$offline += $session->delay;
         }
    }
    return;
}

/**
 * This function calculates for $userid new logs from the last logout
 *
 * @uses register_build_session
 * @link register_build_session
 */
function register_calc_log($register, $userid) {

    if ($register->freezed) {
    	return;
    }

    $sessions = register_get_sessions($register, $userid, 1, 'logout DESC');

    if (is_array($sessions)) {
        foreach ($sessions as $session) {
            $last_session = $session;
            break;
        }
    } else {
        $last_session->logout = 0;
    }

    $sql_str = register_sqlforcourse($register);
    $sql_str .= " AND l.userid = ". $userid ." AND l.time > " . $last_session->logout;

    register_build_session($register, $userid, false, $sql_str);
}

/**
 * Displays 'Recalc all' and 'View all' buttons
 * (if the user has nedded capabilities)
 */
function register_display_general_buttons ($register,$userid) {
    // Get Context
	$cm = get_coursemodule_from_instance("register", $register->id);
	$context = get_context_instance(CONTEXT_MODULE, $cm->id);

	if ( has_capability('mod/register:recalcsessions', $context, NULL, FALSE ) ) {	
	    echo '<form method="get" action="">'."\n";
	    echo "\t".'<input type="hidden" name="a" value="' . $register->id . '" />'."\n";
	    echo "\t".'<input type="hidden" name="recalc" value="1" />'."\n";
	    echo "\t".'<input type="hidden" name="userid" value="0" />'."\n";
	    echo "\t".'<input type="submit" value="' . get_string ("recalcalllogs","register") . '" />'."\n";
	    echo '</form>'."\n";
	}
    if (  has_capability('mod/register:viewotherregisters', $context, NULL, FALSE )  &&  $userid != 0) {
        echo '<form method="get" action="view.php">'."\n";
        echo "\t".'<input type="hidden" name="a" value="' . $register->id . '" />'."\n";
        echo "\t".'<input type="hidden" name="userid" value="0" />'."\n";
        echo "\t".'<input type="submit" value="' . get_string ("seealllogs","register") . '" />'."\n";
        echo '</form>'."\n";
    }
}

/**
 * Display button for printable version
 */
function register_display_printable_button($register,$userid) {
    echo '<form method="get" action="" target="_blank">'."\n";
    echo "\t".'<input type="hidden" name="a" value="' . $register->id . '" />'."\n";
    echo "\t".'<input type="hidden" name="printable" value="1" />'."\n";
    echo "\t".'<input type="hidden" name="userid" value="'. $userid  .'" />'."\n";
    echo "\t".'<input type="submit" value="' . get_string ("showprintableversion","register") . '" />'."\n";
    echo '</form>'."\n";
}

/**
 * Displays total online and offline for user and conditionally display
 * offline per course 
 */
function register_display_total_delay ($register,$userid,$total_online,$total_offline) {
        echo "\t<tr>\n\t\t<th>";
        print_string ("totaldurationonline", "register");
        echo "</th>\n\t\t<td>";
        echo register_format_delay ($total_online);
        echo "</td>\n\t</tr>\n";
        if ($register->offlinesessions) {
            echo "\t<tr>\n\t\t<th>";
            print_string ("totaldurationoffline", "register");
            echo "</th>\n\t\t<td>";
            echo register_format_delay ($total_offline);
            echo "</td>\n\t</tr>\n";
			echo "\t<tr>\n\t\t<th>";
            print_string ("totalduration", "register");
            echo "</th>\n\t\t<td>";
            echo register_format_delay ($total_online + $total_offline);
            echo "</td>\n\t</tr>\n";
        }
}

/**
 * Shows aggregate offline sessions per course
 * @param $offline_courses array of int keyed by courseid
 */
function register_display_offline_courses($register,$userid, $offline_courses) {
    $courses = array();
	if (($register->type != 'normal') && $register->offlinespecifycourse ) { 
        $courses = register_get_my_courses($register, $userid);
	    // Courseid = 0
		if ( isset( $offline_courses[0])  ) {
	    	echo '<tr><th align="right">' . get_string("nospecificourse","register") . '</th>';
	    	echo '<td align="right">' . register_format_delay ($offline_courses[0]) . '</td></tr>';
		}
	    
	    // For every course in metacourse
	    foreach ( $courses as $course ) {
	    	$courseid = $course->id;
	    	$offlinetime = 0;
	    	if ( isset($offline_courses[$courseid]) ) {
	    		$offlinetime = $offline_courses[$courseid];
	    	}
	    	
	    	echo '<tr><th align="right">' . $course->shortname . '</th>';	    	
	    	echo '<td align="right">' . register_format_delay ($offlinetime) . '</td></tr>';
	    }
	    
	}
}

function register_display_offline_certification ($register,$userid,$error) {
    $today = getdate (time());
   
    echo '<div>'; 
    
    print_simple_box_start ('', '', '', 5, 'generalbox', 'register_offlinecertification');    
    if ( $error ) {
        echo '<p class="register_error">' . $error . "</p>\n";
    }

    echo '<form method="post" action="">'."\n";
    print_string ("offlinedeclaration","register");
    
	// If it is in a metacourse and offlinespecifycourse is specified, show courses select list 
	if (($register->type != 'normal') && $register->offlinespecifycourse ) { 

		// Get all courses for the register
        unset ($choices);
        $courses = register_get_my_courses ($register, $userid);

		foreach ($courses as $course ) {
			$choices[$course->id] = $course->fullname;
		}
		if ( $register->mandofflspeccourse ) { 
			$nothingstring = get_string ("selectofflineactivity","register");
		} else {
			$nothingstring = get_string ("offlinegenericactivity","register");
		}
        echo ' ';
		print_string ("offlineactivityabout","register");
        echo ' ';
		choose_from_menu ($choices, 'refcourse', '', $nothingstring, '', '');
	}    
    
    echo '<p>';
    print_string ("date","register");
    echo "\t".'<input type="text" name="fromyear" size="4" maxlength="4" value="' . $today['year'] . '" />'."\n";
    echo "\t - ";
    echo "\t".'<input type="text" name="frommonth" size="2" maxlength="2" value="' . $today['mon'] . '" />'."\n";
    echo "\t - ";
    echo "\t".'<input type="text" name="fromday" size="2" maxlength="2" value="' . $today['mday'] . '" />'."\n";
    echo '<br /><span style="font-size:smaller">' . get_string ("isodate","register");
    echo "</span></p>\n<p>\n\t";

    print_string ("from","register");
    echo " \n\t";
    echo '<input type="text" name="fromhour" size="2" maxlength="2" />';
    echo "\n\t:";
    echo '<input type="text" name="frommin" size="2" maxlength="2" value="00" />';
    echo "\n\t ";
    print_string ("until","register");
    echo " \n\t";
    echo '<input type="text" name="tohour" size="2" maxlength="2" />';
    echo "\n\t:";
    echo '<input type="text" name="tomin" size="2" maxlength="2" value="00" />';
    echo "\n</p>\n";

    // If offlinecomments is specified, shows field
    if ( $register->offlinecomments) {
	    echo "<p>\n\t";
		print_string ("offlineactivity","register");    
	    echo " \n\t";
	    echo '<input type="text" name="comments" size="40" maxlength="255" />';
	    echo "</p>\n";
    }

    echo '<input type="submit" value="' . get_string ("sendcertification","register") . '" name="offline" />';
    echo "\n</form>\n";
    print_simple_box_end();
    
    echo '</div>'; 
    
}

/**
 * Display the <table> containing all session of all user (if $userid = 0)
 * or for a given user (if $userid != 0)
 * 
 * @todo think about rewriting using make_table($table)
 */
function register_display_sessions ($register,$userid = 0,$deletable = true) {

    $strftimedatetime = get_string("strftimedatetime","register");
//    $isteacher = isteacher($register -> course);
    $currently_online = 0;

    $thiscourse = register_get_course($register);  	

    $sessions = register_get_sessions($register,$userid,'','logout DESC');
    
    $current_login = NULL;
    $current_logout = NULL;
    if ($userid != 0) {
    	$currently_online = register_user_current_session ($register,$userid,$current_login,$current_logout);
    }

    if ((!is_array ($sessions)) && (!$currently_online)) {
        echo '<p><b>';
        print_string("nosessionstodisplay", "register");
        echo "</b></p>\n";
        return;
    }

    echo '<table id="register_displaysessions" summary="Sessions list" width="100%" border="0" cellpadding="3" cellspacing="0">'."\n";
    echo "\t<caption>";
    print_string("sessionslist", "register");
    echo "</caption>\n";
    

    echo "\t<thead>\n\t<tr>\n";
    if ($userid == 0) {
    	echo "\t\t<th>".get_string("fullname")."</th>\n";
    }
    echo "\t\t<th colspan=\"2\">".get_string("login","register")."</th>\n";
    echo "\t\t<th colspan=\"2\">".get_string("logout","register")."</th>\n";
    echo "\t\t<th>".get_string("duration","register")."</th>\n";
    if ($register->toleranceevaluation && $register->showtolerance ) {
        echo "\t\t<th>".get_string("tolerance","register")."</th>\n";
    }
    if ($register->offlinesessions) {
        echo "\t\t<th>".get_string("onlineoffline","register")."</th>\n";
    	
    	if ($thiscourse->metacourse  && $register->offlinespecifycourse ) {    	
    		echo "\t\t<th><b>".get_string("course","register")."</b></th>\n";
    	}    	
    	if ( $register->offlinecomments ) {
	    	echo "\t\t<th><b>".get_string("offlineactivity","register")."</b></th>\n";
    	}
        if ( $deletable ) { 
    		echo "\t\t<th><b>".get_string("cancelcertification","register")."</b></th>\n";
        }
    }
    echo "\t</tr>\n\t</thead>\n";

    if ($currently_online) {
        echo "\t<tr class=\"register_onlinesession\">\n";
        if ($userid == 0) {
            // $fullname = fullname(get_record("user","id","$session->userid"), $isteacher);
            $fullname = fullname(get_record("user","id","$session->userid"));
            echo "\t\t".'<td><a href="../../user/view.php?id='."$session->userid&amp;course=$register->course".'" /><b>'.$fullname."</b></td>\n";
        }
        echo "\t\t".'<td style="text-align:left">'.userdate($current_login, '%a')."</td>\n";
        echo "\t\t".'<td style="text-align:left">'.userdate($current_login, $strftimedatetime)."</td>\n";

        echo "\t\t".'<td style="text-align:left">'.userdate($current_logout, '%a')."</td>\n";
        echo "\t\t".'<td style="text-align:left">'.userdate($current_logout, $strftimedatetime)."</td>\n";

        echo "\t\t<td>" . register_format_delay($current_logout - $current_login);
        echo '<br /><span id="register_currentsessionwarning"> (' . get_string("currentsession","register") . ")</span></td>\n";

        if ( $register->toleranceevaluation && $register->showtolerance ) {
        	echo "\t\t<td>0 min</td>\n";
        }

        if ( $register->offlinesessions ) {
   	    	echo "\t\t<td>" . get_string ("online","register") . "</td>\n";
	    	if ($thiscourse->metacourse && $register->offlinespecifycourse ) {     	
    	        echo "\t\t<td>&nbsp;</td>\n";
	    	}
	    	if ( $register->offlinecomments) {
			    echo "\t\t<td>&nbsp;</td>\n";
	    	}
		    if ($deletable) {
			    echo "\t\t<td>&nbsp;</td>\n";
		    }
        } 
        echo "\t</tr>\n";
    }
        
    if (is_array ($sessions)) {
        foreach ($sessions as $session) {
            if ( !$session->online && !$register->offlinesessions ) {
            	continue;
            }
            
            echo "\t<tr class=";
            if ($session->online) {
            	echo '"register_onlinesession"';
            } else { 
            	echo '"register_offlinesession"';
            }
            echo ">\n";
            
            if ($userid == 0) {
                // $fullname = fullname(get_record("user","id","$session->userid"), $isteacher);
                $fullname = fullname(get_record("user","id","$session->userid"));
                echo "\t\t".'<td><a href="../../user/view.php?id='."$session->userid&amp;course=$register->course".'" /><b>'.$fullname."</b></td>\n";
            }

            echo "\t\t".'<td style="text-align:left">'.userdate($session->login, '%a')."</td>\n";
            echo "\t\t".'<td style="text-align:left">'.userdate($session->login, $strftimedatetime)."</td>\n";

            echo "\t\t".'<td style="text-align:left">'.userdate($session->logout, '%a')."</td>\n";
            echo "\t\t".'<td style="text-align:left">'.userdate($session->logout, $strftimedatetime)."</td>\n";

            echo "\t\t<td>".register_format_delay ($session->logout - $session->login)."</td>\n";

            if ($register->toleranceevaluation && $register->showtolerance ) {
            	echo "\t\t<td>".$session -> tolerance." min</td>\n";
            }

            if ($register->offlinesessions ) {
                if ($session->online) {
                	$isonline = get_string ("online","register");
                } else { 
                	$isonline = get_string ("offline","register");
                }
                echo "\t\t<td>".$isonline."</td>\n";

				// If in a metacourse, show refcourse
			   	if ( $thiscourse->metacourse && $register->offlinespecifycourse ) {
					// Retrieve related Course
					if ($session->online) {
						$refcourse_name = '';
					} else {
						$refcourse_name = get_string("notavaliable","register");
						if ($session->refcourse) {
							$refcourse = get_record('course','id',$session->refcourse);
							if ( $refcourse ) {
								$refcourse_name = $refcourse->shortname;
							}
						} 
					}
	                echo "\t\t<td>".$refcourse_name."&nbsp;</td>\n";
			   	}     	
		
		    	if ( $register->offlinecomments ) {
        	        echo "\t\t<td class=\"register_sessioncomments\">". $session->comments ."</td>\n";
		    	}
        		if ( $deletable ) {
					echo "\t\t<td>";
					if ( !$session->online &&  register_updatablesession($session, $register->dayscertificable ) ) {
		                echo '<a href="view.php?a=' . "$register->id&amp;userid=$userid&amp;cancelcertification=$session->id" . '" />' . get_string ("cancel","register");
					}
					echo "</td>\n";
        		}
        	        
            }
            echo "\t</tr>\n";
        }
    }
    echo "\t</table>\n";
}

/**
 * Displays session aggregates for all users in Course(s) associated to the Register.
 * @uses get_course_students retrieve list of students
 * @uses register_calc_log calculate new sessions for every student in Course(s)
 */
function register_display_sessions_aggregate ($register) {

    $users_course = register_get_tracked_users ($register);

    if ( is_array($users_course)) {
        echo '<p align="center">';
        print_string("globalvalues", "register");
        echo "</p>";

        echo '<table border="0" align="center" cellpadding="3" cellspacing="0">';

        echo '<tr >';
        echo '<th  align="left"><font size="2"><b>'.get_string("fullname").'</b></font></th>';
        if ($register->offlinesessions) {
            echo '<th  align="center"><font size="2"><b>'.get_string("totaldurationonline", "register").'</b></font></th>';
            echo '<th  align="center"><font size="2"><b>'.get_string("totaldurationoffline", "register").'</b></font></th>';
        }
        echo '<th  align="center"><font size="2"><b>'.get_string("totalduration", "register").'</b></font></th>';
		echo '</tr >';
		
        foreach ($users_course  as $user_course) {
            register_calc_log ($register, $user_course->id);
            echo '<tr >';

            $fullname = fullname($user_course, true);
            echo '<td ><font size="2"><a href="view.php?a='."$register->id&amp;userid=$user_course->id".'" /><b>'.$fullname.'</b></font></td>';

			$total_online = 0;
			$total_offline = 0;
            register_calc_delay ($register,$user_course -> id,$total_online,$total_offline);

            echo '<td  align="center"><font size="2">'.register_format_delay($total_online).'</font></td>';
            if ($register->offlinesessions) {
                echo '<td  align="center"><font size="2">'.register_format_delay($total_offline).'</font></td>';
                echo '<td  align="center"><font size="2">'.register_format_delay($total_offline + $total_online).'</font></td>';
            }

            echo '</tr>';
            flush();
        }
        echo '</table>';
    } else {
        echo '<p align="center">';
        print_string("nousers", "register");
        echo '</p>';
    }
}
/**
 * Insert a new record in register_logs for a single user session
 */
function register_insert_session ($registerid, $userid, $login, $last_hit, $toleranceevaluation, $online, $wait, $refcourse = 0, $comments = NULL) {
    $log_data = NULL;
    $log_data->register = $registerid;
    $log_data->userid = $userid;
    $log_data->online = $online;
    $log_data->login = $login;
    $log_data->refcourse = $refcourse;
    $log_data->comments = $comments;
    if ($toleranceevaluation) {
        $log_data->logout = $last_hit + ($wait * 60 / 2);
        $log_data->tolerance = $wait / 2;
    } else {
        $log_data->logout = $last_hit + ($wait * 60);
        $log_data->tolerance = 0;
    }
    insert_record("register_logs", $log_data);
    return;
}

/**
 * This function recalculates all logs for all users
 *
 * It also manage web page redirection to avoid browser timeout or PHP server timeout
 * @uses register_build_session
 * @link register_build_session
 */
function register_recalc_all_logs ($register, $userid, $first_log = 0, $display = true) {

	if (($register->freezed) && ($userid == 0)) 
    	return;

    if ($userid == 0) {
        // looking for the first user in the course
        // $users_course = get_course_students ($register->course,"u.id");
	    
	    $users_course = register_get_tracked_users($register, 'u.id, u.username' , 'register_compare_users_by_id');
        
        if (!is_array ($users_course)) {
        	return;
        }
        foreach ($users_course as $user_course) {
            $userid = $user_course->id;
            break;
        }
    }

    $sql_str = register_sqlforcourse($register);
    $sql_str = $sql_str . " AND l.userid = " . $userid;

    $register->freezed = 1;
    update_record("register", $register);
    
    if ($first_log == 0) 
    	delete_records("register_logs", "register", "$register->id", "online", "1", "userid", $userid);

    $end = register_build_session ($register, $userid, $display, $sql_str, $first_log, REGISTER_MINIMUM_LOGS_FOR_PAGE);

    // redirection for the same $userid, but new logs
    if ($end > 0) 
    	redirect("view.php?a=$register->id&amp;userid=$userid&amp;recalc=1&amp;log=$end",get_string ("continue"),1);

    // $users_course = get_course_students ($register->course,"u.id");
	$users_course = register_get_tracked_users($register, 'u.id, u.username', 'register_compare_users_by_id');
    
	foreach ($users_course as $user_course) {
        // redirection for the next user
        if ($userid < $user_course->id) 
        	redirect("view.php?a=$register->id&amp;userid=$user_course->id&amp;recalc=1&amp;log=0",get_string ("continue"),1);
    }
    $register->freezed = 0;
    $userid = 0;
    update_record("register", $register);
}

function register_format_delay ($delay) {
    $sec = $delay % 60;
    $min = floor($delay / 60) % 60;
    $h = floor ($delay / 3600);
    return sprintf("%02d:%02d:%02d",$h,$min,$sec);
}

function register_insert_offline_certification ($register,$userid,$fromyear,$frommonth,$fromday,$fromhour,$frommin,$tohour,$tomin,$comments, $refcourse) {
    $valid = true;
    $error = '';

	$session = NULL;
    $session->register = $register->id;
    $session->login = mktime( $fromhour,$frommin,0,$frommonth,$fromday,$fromyear);
    $session->logout = mktime( $tohour,$tomin,0,$frommonth,$fromday,$fromyear);
    
    if (  !$session->login || $session->login < 0
    	|| !$session->logout || $session->logout < 0) {
    	$valid = false;
    	$error = get_string ("invalidtime","register");
    	return $error;    
    }
    
    if ($register->toleranceevaluation ) {
    	$session->tolerance = 1;
    } else { 
    	$session->tolerance = 0;
    }
    $session->userid = $userid;
    $session->online = 0;
    if ( $register->offlinespecifycourse ) {
    	$session->refcourse = $refcourse;
    } else {
	   	$session->refcourse = 0;
    }

   	$session->comments = NULL;
    if ( $register->offlinecomments ) {
    	$session->comments = trim($comments);
    	if ( !($session->comments) ) {
		   	$session->comments = NULL;
    	}
    }
    
    if ( $session->login >= $session->logout) {
    	$valid = false;
    	$error = get_string ("invalidtime","register");
    } else if (!register_updatablesession ($session, $register->dayscertificable )) {
        $valid = false;
        $error = get_string ("sessionnotupdatable","register");
    } else if (register_sessionconflict($register,$userid,$session)) {
        $valid = false;
        $error = get_string ("sessionconflict","register");
    } 
    // Check comments if mandatory
    else if ($register->offlinecomments && $register->mandatoryofflinecomm && !$session->comments  ) {
        $valid = false;
        $error = get_string ("commentismandatory","register");
    }    
    // Check course if mandatory and current course is metacourse
    else if ( $register->offlinespecifycourse && $register->mandofflspeccourse && !($session->refcourse)  ) {
    	$thiscourse = register_get_course($register);
    	if ( $thiscourse->metacourse )  {
	        $valid = false;
	        $error = get_string ("courseismanadatory","register");
    	}  	
    }
    
	if ($valid) 
    	insert_record("register_logs", $session);
    
    return $error;
}

///**
// * @deprecated this function is not used, but you can insert it to know when
// * you have so many logs to calculate that is better to recalculate all logs
// */
//function register_needrecalc ($register) {
//
//    $sessions = register_get_sessions($register,0,1,'logout DESC');
//
//    if (is_array ($sessions)) {
//    
//        foreach ($sessions as $session) {
//            if (((!isset ($last_sessions_logout [$session -> userid])) || ($last_sessions_logout [$session -> userid]) < $session -> logout))
//                $last_sessions_logout [$session -> userid] = $session -> logout;
//        }
//        $logout = array_sum ($last_sessions_logout) / count ($last_sessions_logout);
//    }
//    else $logout = 0;
//    
//    $sql_str = register_sqlforcourse($register);
//    $sql_str = $sql_str . " AND l.time > " . $logout;
//
//	$countlogs = 0;
//    get_logs ($sql_str,"l.time DESC","","",$countlogs);
//    
//    if ($countlogs > REGISTER_MINIMUM_LOGS_FOR_PAGE) return true;
//    return false;
//}

/**
 * Check if a given session overlap any session already in user register
 * (both online or offline)
 */
function register_sessionconflict($register,$userid,$session) {
    
	$sessions = register_get_sessions($register,$userid);

	$current_login = NULL;
	$current_logout = NULL;
    $currently_online = register_user_current_session ($register, $userid, $current_login, $current_logout);

    if ($currently_online) {
        $result = false;
        if ( ($session->login > $current_login) && ($session->login < $current_logout) ) { 
        	$result = true;
        }
        if ( ($session->logout > $current_login) && ($session->logout < $current_logout) ) { 
        	$result = true;
        }
        if ($result) { 
        	return $result;
        }
    }
    if (!is_array ($sessions)) { 
    	return false;
    }
    $result = false;

    foreach ($sessions as $sess) {
        if ( ($session->login > $sess->login) && ($session->login < $sess->logout) ) { 
        	$result = true;
        }
        if ( ($session->logout > $sess->login) && ($session->logout < $sess->logout) ) { 
        	$result = true;
        }
        if ( ($session->login <= $sess->login) && ($session->logout >= $sess->logout) ) { 
        	$result = true;
        }
        if ($result) { 
        	return $result;
        }
    }
    return false;
}

function register_updatablesession ($session, $dayscertificable) {
    $updatablesession = true;
    $today = getdate (time());
    $firstpossiblelogin = mktime (0,0,0, $today['mon'], $today['mday'] - $dayscertificable, $today['year']);

    if ($session->online == 1) 
    	$updatablesession = false;
    if ($session->logout > time()) 
    	$updatablesession = false;
    if ($session->login < $firstpossiblelogin) 
    	$updatablesession = false;
    return $updatablesession;
}

/**
 * Returns all "my" courses tracked by the register
 * @return an array of courses. 
 */
function register_get_my_courses($register,$userid) {
    switch ($register->type) {
        case 'meta':
	        $courses = register_get_my_courses_in_metacourse($register->course, $userid);
		    break;
		case 'category':
		    $courses = register_get_my_courses_in_category($register->course, $userid);
		    break;
    }
    return $courses;
}


/**
 * Get the all "my" courses of a given user, 
 * included in a given list of course objects
 * (returns the intersection of the two arrays)
 *
 * @param $userid user id
 * @param $courselist array of Courses
 * @return array of Courses
 */
function register_get_my_courses_in_courselist($userid, $courselist) {
	// Get IDs of Courses in the list 
	$courseidlist = array();
	foreach ($courselist as $course) {
		$courseidlist[] = $course->id;
	}

	// get all "my" courses
	$mycourses = get_my_courses($userid);
	
	// keep only my courses in the list
	$mycoursesinlist = array();
	foreach ($mycourses as $course) {
		if ( in_array( $course->id, $courseidlist ) ) {
			$mycoursesinlist[] = $course;
		}
	}
	
	return $mycoursesinlist;
}

/**
 * Returns all "my" courses belonging to a specified metacourse
 * @return an array of courses. 
 * 
 */
function register_get_my_courses_in_metacourse($metacourseid,$userid) {
	
	// Get all id of courses in the metacourse
	$coursesinmeta = get_courses_in_metacourse($metacourseid);

	// Get all my courses in metacourse
	return register_get_my_courses_in_courselist($userid, $coursesinmeta);
}

/**
 * Returns all "my" courses in a given category
 * @return an array of courses. 
 * 
 */
function register_get_my_courses_in_category($courseid, $userid) {

	// Get all courses in the same category of the given course
	$course = get_record ('course','id',$courseid);
	$coursesincategory = get_courses($course->category);

	// Get all my courses in the same category
	return register_get_my_courses_in_courselist($userid, $coursesinmeta);	
}

/**
 * Display the main part of user sessions page
 */
function register_display_main_contents($register, $userid , $printable = 0, $error_certification = NULL) {
	global $USER;
    
	// Get Context
	$cm = get_coursemodule_from_instance("register", $register->id);
	$context = get_context_instance(CONTEXT_MODULE, $cm->id);
	
	$course = register_get_course($register);
    
//    // Setup table formatting
//    $headcellalign='center';
//    if ( !$printable && ($userid == $USER -> id) && ($register -> offlinesessions) ) {
//	    $headcellalign='left';
//    }

    echo '<div id="register_generalinfo">'."\n";
    if (!$printable) {
      echo '<div id="register_generalbuttons">'."\n";
	  register_display_printable_button($register, $userid);
//    // If you are a teacher, you'll be able to recalculate all logs and to see all logs of your students
//    if (isteacher($course -> id)) {
       register_display_general_buttons ($register, $userid);
//    }
      echo '</div>'."\n";
    }
    if ($userid != 0) {
        echo '<div id="register_user_summary" >'. "\n<p>\n";
        
        $user = get_record ("user","id",$userid);

        // Shows user's totals
        echo '<table summary="aggregate values for online and offline sessions" class="register_globalvalues" cellpadding="3" border="0" cellspacing="0">'."\n\t";
		echo '<caption>';
	    print_string("globalvalues", "register");
	    echo " " . get_string ("of","register") . " " . fullname($user);
        echo '</caption>'."\n";

        $offline_courses = array();
        // Calculate offline time per course
		if ( $register -> offlinespecifycourse ) {
            $offline_courses = register_calc_offline_courses($register,$userid);
		}

        // if you want sessions about a single user, it'll print also global value:
        // how much time user spent offline and online as aggregate value
        $total_online = 0;
        $total_offline = 0;
        register_calc_delay ($register,$userid,$total_online,$total_offline);

        register_display_total_delay ($register,$userid,$total_online, $total_offline);
        echo '</table>'."\n</p><p>\n";
        
        // Conditionally shows offline per course
        if ( ($register->type != 'normal') && $offline_courses && count($offline_courses) > 0 ) {
            echo '<table summary="shows offline per course" class="register_globalvalues" cellpadding="3" border="0" cellspacing="0">'."\n\t<caption>";
            print_string ("offlinetimebycourse", "register");
            echo '</caption>'."\n";
            register_display_offline_courses($register,$userid, $offline_courses);
           	echo '</table>'."\n";
        }
        echo '</p></div>'."\n"; // #register_user_summary
        
    	// I'll display offline certification form, if user is looking his logs and offlinesessions option is on
	    if ( !$printable && ($userid == $USER->id)&&($register->offlinesessions)) {
        	register_display_offline_certification ($register, $USER->id, $error_certification);
        }
    }
   echo '</div>'."\n"; // #register_generalinfo

    echo '<div id="register_sessions">';
	// if no user specified show aggregates for all users
    if ($userid != 0) {
    	if ( $printable ) {
    		$deletable = false;
    	} else {
    		// Record is deletable if: (is own, user is _real_ and has capability) or (is not own and user has capability)
    		$deletable = ( $userid == $USER->id
    					   && has_capability('mod/register:deleteownselfcert', $context, NULL, FALSE) 
    					   && empty($USER->realuser) )
    				  || ( $userid != $USER->id
    				  	   && has_capability('mod/register:deleteotherselfcert', $context, NULL, FALSE)  );
    	}
    	register_display_sessions($register,$userid,$deletable , $register -> offlinesessions);
    }
    // Otherwhise show all session of the specified user
    else {
    	register_display_sessions_aggregate ($register, $register -> offlinesessions);
    }
	echo '</div>'."\n"; // #register_sessions
	
}

/**
 * Print page header for printable version
 * Includes printableheader.html
 * 
 */
function register_print_printable_header($register, $userid) {
   $meta = '';
   
   if ( get_string('thisdirection') == 'rtl' ) {
        $direction = ' dir="rtl"';
    } else {
        $direction = ' dir="ltr"';
    }

   if (!empty($CFG->unicode)) {
        $encoding = 'utf-8';
    } else if (!empty($CFG->courselang)) {
        $encoding = get_string('thischarset');
        moodle_setlocale();
    } else {
        if (!empty($SESSION->encoding)) {
            $encoding = $SESSION->encoding;
        } else {
            $SESSION->encoding = $encoding = get_string('thischarset');
        }
    }
    $meta = '<meta http-equiv="content-type" content="text/html; charset='. $encoding .'" />'. "\n". $meta ."\n";
	// Do everything we can to always prevent clients and proxies caching
    @header('Cache-Control: no-store, no-cache, must-revalidate');
    @header('Cache-Control: post-check=0, pre-check=0', false);
    @header('Pragma: no-cache');
    @header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
    @header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');

    $meta .= "\n<meta http-equiv=\"pragma\" content=\"no-cache\" />";
    $meta .= "\n<meta http-equiv=\"expires\" content=\"0\" />";
    
    @header('Accept-Ranges: none');
    $title = get_string("modulename","register");

    include ('./printableheader.html');
}	

/**
 * Print page footer for prinable version
 * Includez printablefooter.html
 */
function register_print_printable_footer() {
    include ('./printablefooter.html');
}
?>
