[moodle] / contrib / plugins / grade / report / visual / lib.php Repository:

View of /contrib/plugins/grade/report/visual/lib.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (download) (annotate)
Sat Aug 2 12:19:15 2008 WST (15 months, 3 weeks ago) by dservos
Branch: MAIN
Changes since 1.3: +13 -10 lines
CONTRIB-497
*Added more visualizations
*Added selector UI Widget for flex/flare visualization
*Refactored some of flex actionscript code.
*Added defaults for selected group and items in visualizations.
*Improved removal of nodes and edges when an item or group is deselected in a legend.
*Fixed a memory leak realting to the removal and addtion of nodes.
*Added more options for and control of the flex/flare based visualization from the Moodle back end.
<?php
 ///////////////////////////////////////////////////////////////////////////
//                                                                       //
// NOTICE OF COPYRIGHT                                                   //
//                                                                       //
// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
//          http://moodle.org                                            //
//                                                                       //
// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
//                                                                       //
// This program is free software; you can redistribute it and/or modify  //
// it under the terms of the GNU General Public License as published by  //
// the Free Software Foundation; either version 2 of the License, or     //
// (at your option) any later version.                                   //
//                                                                       //
// This program is distributed in the hope that it will be useful,       //
// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
// GNU General Public License for more details:                          //
//                                                                       //
//          http://www.gnu.org/copyleft/gpl.html                         //
//                                                                       //
///////////////////////////////////////////////////////////////////////////
 
 
require_once($CFG->dirroot . '/grade/report/lib.php');
require_once($CFG->libdir.'/tablelib.php');

foreach (glob($CFG->dirroot . '/grade/report/visual/visualizations/visual_*.php') as $filename) {
   require_once($filename);
}

class grade_report_visual extends grade_report {
    /**
     * Capability to view hidden items.
     * TODO: Add a check for hidden items and grades.
     * @var bool $canviewhidden
     */
    public $canviewhidden;
    
    public $nullgradesasmin = false;
    
    private static $visualizations = array();
    
    /**
     * Grade objects of users in the course
     * @var array $grades
     */
    public $grades = array();
    
    private $visdata = array();
    
    private $visid = 'grades_vs_students';
    
    private $flashvars = array();

    private $flashvarshtml;
   
    /**
     * The html of the report to output.
     * @var string $html
     */     
    public $html;
    

    /**
     * Constructor. Initialises grade_tree, sets up group, baseurl
     * and pbarurl.
     * @param int $courseid the coures id for the report
     * @param object $gpr grade plugin tracking object
     * @context string $context
     */
    public function __construct($courseid, $gpr, $context, $visid=null) {
        global $CFG;
        parent::__construct($courseid, $gpr, $context, null);

        $this->canviewhidden = has_capability('moodle/grade:viewhidden', get_context_instance(CONTEXT_COURSE, $this->course->id));
        
        if(!is_null($visid)) {
            $this->visid = $visid;
        }
        
        /// Set up urls
        $this->baseurl = 'index.php?id=' . $this->courseid;
        $this->pbarurl = 'index.php?id=' . $this->courseid;
    
        /// Build grade tree
        $this->gtree = new grade_tree($this->courseid, false);
        
        $this->load_visualizations();
        $this->set_up_flashvars();
        
        /// Set up Groups
        if($visid && grade_report_visual::get_visualization($visid)->usegroups) {
            $this->setup_groups();
        }
    }

    /// Added to keep grade_report happy
    public function process_data($data){}
    public function process_action($target, $action){}

    /**
     * Load all the visualization classes into $visualizations.
     * Looks in /visualizations and trys to make an instence of any
     * class that is in a file that starts with visual_ and extends 
     * visualization directly.
     * @param bool $return if true return visualizations array, else store in $this->visualizations
     * @returns array array of clases that extend visualization
     */
    private function load_visualizations($return=false) {
        global $CFG;
        
        if(!isset(grade_report_visual::$visualizations) || is_null(grade_report_visual::$visualizations) || empty(grade_report_visual::$visualizations)) {
            $visualizations = array();
        
            foreach (glob($CFG->dirroot . '/grade/report/visual/visualizations/visual_*.php') as $path) {
                $filename = substr(basename($path, '.php'), 7);

                if(class_exists($filename) && get_parent_class($class = new $filename) == 'visualization' ) {
                    $visualizations[$filename] = $class;
                }
            }
        
            if($return) {
                return $visualizations;
            } else {
                grade_report_visual::$visualizations = $visualizations;
            }
        } else if($return) {
            return grade_report_visual::$visualizations;
        }
    }
    
    /**
     * Returns the current visualizations being used in the report
     * or if none are set, it returns the them as whould be loaded
     *  by load_visualizations.
     * @returns array array of classes that extend visualization
     */
    public function get_visualizations() {
        if(!isset(grade_report_visual::$visualizations) || is_null(grade_report_visual::$visualizations) || empty(grade_report_visual::$visualizations)) {
            return grade_report_visual::load_visualizations(true);
        } else {
            return grade_report_visual::$visualizations;
        }
    }
    
    public function get_visualization($filename) {
        if(!isset(grade_report_visual::$visualizations) || is_null(grade_report_visual::$visualizations) || empty(grade_report_visual::$visualizations) || is_null(grade_report_visual::$visualizations[$filename])) {
            if(class_exists($filename) && get_parent_class($class = new $filename) == 'visualization' ) {
                return $class;
            } else {
                return null;
            }
        } else {
            return grade_report_visual::$visualizations[$filename];
        }
    }

    /**
     * Based on load user function from grader report.
     * Pulls out the userids of the users to be used in the stats.
     * @return array array of user ids to use in stats
     */
    public function load_users() {
        global $CFG, $DB;
        
        if(isset($DB) && !is_null($DB)) {
            $params = array();
            list($usql, $gbr_params) = $DB->get_in_or_equal(explode(',', $this->gradebookroles));
        
            $sql = "SELECT u.id, u.firstname, u.lastname, u.imagealt, u.picture, u.idnumber, u.username
                    FROM {user} u
                        JOIN {role_assignments} ra ON u.id = ra.userid
                        $this->groupsql
                    WHERE ra.roleid $usql
                        $this->groupwheresql
                        AND ra.contextid ".get_related_contexts_string($this->context);
        
            $params = array_merge($gbr_params, $this->groupwheresql_params);
            $this->users = $DB->get_records_sql($sql, $params);
        } else {
            $sql = "SELECT u.id, u.firstname, u.lastname, u.imagealt, u.picture, u.idnumber
                      FROM {$CFG->prefix}user u
                           JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid
                           $this->groupsql
                     WHERE ra.roleid in ($this->gradebookroles)
                           $this->groupwheresql
                           AND ra.contextid ".get_related_contexts_string($this->context);
        
            $this->users = get_records_sql($sql);
        }

        if (empty($this->users)) {
            $this->userselect = '';
            $this->users = array();
            $this->userselect_params = array();
        } else {
            if(isset($DB) && !is_null($DB)) {
                list($usql, $params) = $DB->get_in_or_equal(array_keys($this->users));
                $this->userselect = "AND g.userid $usql";
                $this->userselect_params = $params;
            }else{
                $this->userselect = 'AND g.userid in ('.implode(',', array_keys($this->users)).')';
            }
        }
        
        return $this->users;
    }
    
    /**
     * Harvest the grades from the data base and build the finalgrades array.
     * Filters out hidden, locked and null grades based on users settings.
     * Partly based on grader reports load_final_grades function.
     */
    public function harvest_data() {
        global $CFG, $DB;

        $params = array();

        if(isset($DB) && !is_null($DB)) {
            $params = array_merge(array($this->courseid), $this->userselect_params);
            
            /// please note that we must fetch all grade_grades fields if we want to contruct grade_grade object from it!
            $sql = "SELECT g.*
                  FROM {grade_items} gi,
                       {grade_grades} g
                 WHERE g.itemid = gi.id AND gi.courseid = ? {$this->userselect}";
            
            $grades = $DB->get_records_sql($sql, $params);
        } else {
            /// please note that we must fetch all grade_grades fields if we want to contruct grade_grade object from it!
            $sql = "SELECT g.*
                  FROM {$CFG->prefix}grade_items gi,
                       {$CFG->prefix}grade_grades g
                 WHERE g.itemid = gi.id AND gi.courseid = {$this->courseid} {$this->userselect}";
            
            $grades = get_records_sql($sql);
        }
        
        $userids = array_keys($this->users);

        if ($grades) {
            foreach ($grades as $graderec) {
                if (in_array($graderec->userid, $userids) and array_key_exists($graderec->itemid, $this->gtree->items)) { // some items may not be present!!
                    $this->grades[$graderec->itemid][$graderec->userid] = new grade_grade($graderec, false);
                    $this->grades[$graderec->itemid][$graderec->userid]->grade_item =& $this->gtree->items[$graderec->itemid]; // db caching
                }
            }
        }

        if($this->nullgradesasmin) {
        /// prefil grades that do not exist yet
            foreach ($userids as $userid) {
                foreach ($this->gtree->items as $itemid=>$unused) {
                    if (!isset($this->grades[$itemid][$userid])) {
                        $this->grades[$itemid][$userid] = new grade_grade();
                        $this->grades[$itemid][$userid]->itemid = $itemid;
                        $this->grades[$itemid][$userid]->userid = $userid;
                        $this->grades[$itemid][$userid]->grade_item =& $this->gtree->items[$itemid]; // db caching
                        $this->grades[$itemid][$userid]->finalgrade = $this->grades[$itemid][$userid]->grade_item->mingrade;
                    }
                }
            }
        }

        /*$this->finalgrades = array();

        /// Build finalgrades array and filliter out unwanted grades.
        foreach ($this->gtree->items as $id=>$item) {
            if(($item->gradetype == GRADE_TYPE_SCALE &&  ($this->get_pref('stats', 'showscaleitems') || is_null($this->get_pref('stats', 'showscaleitems')))) 
                || ($item->gradetype == GRADE_TYPE_VALUE &&  ($this->get_pref('stats', 'showvalueitems') || is_null($this->get_pref('stats', 'showvalueitems'))))) {             
                    $this->finalgrades[$id] = array();
                    $i = 0;
                    
                    if(isset($this->grades[$id]) && !is_null($this->grades[$id])) {
                        foreach ($this->grades[$id] as $grade) {
                            if( (($grade->is_hidden() && ($this->get_pref('stats', 'usehidden') || is_null($this->get_pref('stats', 'usehidden')))) || !$grade->is_hidden())
                                && (($grade->is_locked() && ($this->get_pref('stats', 'uselocked') || is_null($this->get_pref('stats', 'uselocked')))) || !$grade->is_locked())) {
                                    if($this->get_pref('stats', 'incompleasmin') && is_null($grade->finalgrade)) {
                                        $this->finalgrades[$id][$i] = $item->grademin;
                                        $i++;
                                    } elseif(!is_null($grade->finalgrade)) {
                                        $this->finalgrades[$id][$i] = $grade->finalgrade;
                                        $i++;
                                    }
                            }               
                        }
                    }
                }
        }*/
    }

    /**
    * TODO: have this make the data depending on what kind of visulsation
    * is needed rather then a singal visulasztion witch is currently hardcoded.
    */
    public function report_data($all = false) {
        if($all) {
            $visuals = $this->get_visualizations();
        
            foreach($visuals as $key=>$visual) {
                $this->visdata[$key] = $visual->report_data($this);
            }
        } else {
            $visual = $this->get_visualization($this->visid);
            $this->visdata[$this->visid] = $visual->report_data($this);
        }
    }

    private function set_up_flashvars() {
        global $USER, $SESSION, $CFG;
    
        $flashvars = array();
        $flashvars['username'] = $USER->username;
        $flashvars['userid'] = $USER->id;
        $flashvars['courseid'] = $this->courseid;
        $flashvars['coursefullname'] = $this->course->fullname;
        $flashvars['courseshortname'] = $this->course->shortname;
        $flashvars['sessionid'] = session_id();
        $flashvars['sessioncookie'] = $CFG->sessioncookie;
        $flashvars['sessiontest'] = $SESSION->session_test;
        $flashvars['dirroot'] = $CFG->dirroot;
        $flashvars['wwwroot'] = $CFG->wwwroot;
        $flashvars['visid'] = $this->visid;
        
        foreach($flashvars as $key=>$val) {
            $this->flashvarshtml .= $key. '=' . addslashes(urlencode(strip_tags($val))) . '&';
        }
        $this->flashvarshtml = substr($this->flashvarshtml, 0, strlen($this->flashvarshtml) - 1);
    }

    /**
    *TODO: Have this call on flex.php to generate html for the report.,
    *rather then having it hardcoded as it is now.
    */
    public function adapt_html($printerversion = false, $return = false) {
        global $CFG;
        
        $flashvarshtml = $this->flashvarshtml;
        $visual = $this->get_visualization($this->visid);
        
        ob_start();
        require($CFG->dirroot.'/grade/report/visual/flex.php');
        $this->html = ob_get_clean();
        
        if($return) {
            return $this->html;
        } else {
            echo $this->html;
        }
    }
    
    public function adapt_data($return = false) {
        if($return) {
            return $this->get_tab(true);
        } else {
            echo $this->get_tab(true);
        }
    }
    
    public function visualization_selector($return = false) {
        $visuals = $this->get_visualizations();
        $visualmenu = array();
        $vislabel = $this->get_lang_string('visualselector', 'gradereport_visual');
        
        foreach($visuals as $key=>$visual) {
            $visualmenu[$key] = format_string($visual->name);
        }
        
        if(count($visualmenu) > 1) {
            $selectorhtml =  popup_form($this->pbarurl . '&amp;visid=', $visualmenu, 'selectvisual', $this->visid, '', '', '', true, 'self', $vislabel);
        } else {
            $selectorhtml = '';
        }
    
        if($return) {
            return $selectorhtml;
        } else {
            echo $selectorhtml;
        }
    }
    
    public static function truncate($string, $max = 25, $end = '...') {
        if(strlen($string) <= $max) {
            return $string;
        }
        
        return substr_replace($string, $end, $max - strlen($end));
    }
    
    /**
     * Returns the data for a visulazation in json format.
     * TODO: Use moodle's json encoding functions rather then phps.
     * @param boolean $return if true return a string, other wise echo the data.
     * @return string If return is set to true, returns a string of the data in json format.
     */
    private function get_json($return = true) {
        if ($return) {
            return json_encode($this->visdata[$this->visid]);
        } else {
            echo json_encode($this->visdata[$this->visid]);
        }
    }
    
    /**
     * Returns the data for a visulasation in tab format.
     * @param boolean $return if true return a string, other wise echo the data.
     * @return string If return is set to true, returns a string of the data in tab format.
     */
    private function get_tab($return = true) {
        if ($return) {
            return $this->tab_encode($this->visdata[$this->visid]);
        } else {
            echo $this->tab_encode($this->visdata[$this->visid]);
        }
    }
    
    /**
     * Encodes an array to a string using the tab format.
     *@param array $data the array to encode.
     *@return string a string encoded in tab format based on the given array.
     */
    public static function tab_encode(array $data, $useindexes = false) {
        $outstring = '';
        
        foreach($data as $key=>$row) {
            if(is_array($row)) {
                if($useindexes) {
                    $outstring .= $key . "\t";
                }
            
                foreach($row as $col) {
                    $outstring .= $col . "\t";
                }
                
                $outstring[strlen($outstring) - 1] = "\n";
            } else {
                if($useindexes) {
                    $outstring .= $key . "\t" . $row . "\n";
                } else {
                    $outstring .= $row . "\n";
                }
            }
        }
        
        return $outstring;
    }
}
?>

Moodle CVS Admin
ViewVC Help
Powered by ViewVC 1.0.7