session_get_instance()->write_close(); // release session
- header('Content-Type: application/xhtml+xml');
+ header('Content-Type: application/xhtml+xml; charset=utf-8');
header('Content-Disposition: attachment; filename=database.xml');
header('Expires: 0');
header('Cache-Control: must-revalidate,post-check=0,pre-check=0');
}
// Settings link, if available.
- if (file_exists($qtype->plugin_dir() . '/settings.php')) {
+ $settings = admin_get_root()->locate('qtypesetting' . $qtypename);
+ if ($settings instanceof admin_externalpage) {
+ $row[] = '<a href="' . $settings->url .
+ '">' . get_string('settings') . '</a>';
+ } else if ($settings instanceof admin_settingpage) {
$row[] = '<a href="' . admin_url('settings.php?section=qtypesetting' . $qtypename) .
'">' . get_string('settings') . '</a>';
} else {
// Question type settings.
$ADMIN->add('modules', new admin_category('qtypesettings', get_string('questiontypes', 'admin')));
$ADMIN->add('qtypesettings', new admin_page_manageqtypes());
- require_once($CFG->libdir . '/questionlib.php');
- global $QTYPES;
- foreach ($QTYPES as $qtype) {
- $settingsfile = $qtype->plugin_dir() . '/settings.php';
+ $qtypes = get_plugin_list('qtype');
+ foreach ($qtypes as $qtype => $path) {
+ $settingsfile = $path . '/settings.php';
if (file_exists($settingsfile)) {
- $settings = new admin_settingpage('qtypesetting' . $qtype->name(),
- $qtype->local_name(), 'moodle/question:config');
+ $settings = new admin_settingpage('qtypesetting' . $qtype,
+ get_string('pluginname', 'qtype_' . $qtype), 'moodle/question:config');
include($settingsfile);
if ($settings) {
$ADMIN->add('qtypesettings', $settings);
$courseid = $ccache[$shortname]->id;
$coursecontext = get_context_instance(CONTEXT_COURSE, $courseid);
if (!isset($manualcache[$courseid])) {
- if ($instances = enrol_get_instances($courseid, false)) {
- $manualcache[$courseid] = reset($instances);
- } else {
- $manualcache[$courseid] = false;
+ $manualcache[$courseid] = false;
+ if ($manual) {
+ if ($instances = enrol_get_instances($courseid, false)) {
+ foreach ($instances as $instance) {
+ if ($instance->enrol === 'manual') {
+ $manualcache[$courseid] = $instance;
+ break;
+ }
+ }
+ }
}
}
echo $OUTPUT->footer();
break;
case ACTION_GENERATE_XML:
- header('Content-type: application/xhtml+xml');
+ header('Content-type: application/xhtml+xml; charset=utf-8');
echo $xmldb_action->getOutput();
break;
}
$courses_limit = $courses_limit + 1;
}
- $courses = enrol_get_my_courses('id, shortname', 'visible DESC,sortorder ASC', $courses_limit);
+ $courses = enrol_get_my_courses('id, shortname, modinfo', 'visible DESC,sortorder ASC', $courses_limit);
$site = get_site();
$course = $site; //just in case we need the old global $course hack
header('Accept-Ranges: none'); // Comment out if PDFs do not work...
header('Content-disposition: attachment; filename='.$filename);
header('Content-length: '.strlen($serialized));
-header('Content-type: text/calendar');
+header('Content-type: text/calendar; charset=utf-8');
echo $serialized;
// used? set to 'false' for the most stable
// setting, 'true' can improve performance
// sometimes
- 'dbsocket' => false, // should connection via UNIX socket be
- // used? if you set it to 'true' here,
- // set dbhost to 'localhost'
+ 'dbsocket' => false, // should connection via UNIX socket be used?
+ // if you set it to 'true' or custom path
+ // here set dbhost to 'localhost',
+ // (please note mysql is always using socket
+ // if dbhost is 'localhost' - if you need
+ // local port connection use '127.0.0.1')
'dbport' => '', // the TCP port number to use when connecting
// to the server. keep empty string for the
// default port
$table->head = array(
get_string('time'),
get_string('ip_address'),
- get_string('fullnamecourse'),
+ get_string('fullname'),
get_string('action'),
get_string('info')
);
unset($user_mapping);
// enrol all users and sync roles
- foreach ($requested_roles as $userid=>$roles) {
- foreach ($roles as $roleid) {
+ foreach ($requested_roles as $userid=>$userroles) {
+ foreach ($userroles as $roleid) {
if (empty($current_roles[$userid])) {
$this->enrol_user($instance, $userid, $roleid);
$current_roles[$userid][$roleid] = $roleid;
// unassign removed roles
foreach($current_roles[$userid] as $cr) {
- if (empty($roles[$cr])) {
+ if (empty($userroles[$cr])) {
role_unassign($cr, $userid, $context->id, 'enrol_database', $instance->id);
unset($current_roles[$userid][$cr]);
}
}
function outputText($texexp) {
- header("Content-type: text/html");
+ header("Content-type: text/html; charset=utf-8");
echo "<html><body><pre>\n";
if ($texexp) {
$texexp = str_replace('<','<',$texexp);
function outputText($texexp) {
- header("Content-type: text/html");
+ header("Content-type: text/html; charset=utf-8");
echo "<html><body><pre>\n";
if ($texexp) {
$texexp = str_replace('<', '<', $texexp);
continue;
}
- // this was idnumber
- $gradeitems[$grade_item->id] = $grade_item->get_name();
+ $displaystring = null;
+ if (!empty($grade_item->itemmodule)) {
+ $displaystring = get_string('modulename', $grade_item->itemmodule).': '.$grade_item->get_name();
+ } else {
+ $displaystring = $grade_item->get_name();
+ }
+ $gradeitems[$grade_item->id] = $displaystring;
}
}
}
if ($importcode = optional_param('importcode', '', PARAM_FILE)) {
$filename = $CFG->dataroot.'/temp/gradeimport/cvs/'.$USER->id.'/'.$importcode;
$fp = fopen($filename, "r");
- $header = explode($csv_delimiter, fgets($fp,GRADE_CSV_LINE_LENGTH), PARAM_RAW);
+ $headers = fgets($fp, GRADE_CSV_LINE_LENGTH);
+ $header = explode($csv_delimiter, $headers);
+ fclose($fp);
}
$mform2 = new grade_import_mapping_form(null, array('gradeitems'=>$gradeitems, 'header'=>$header));
$fp = fopen($filename, "r");
// --- get header (field names) ---
- $header = explode($csv_delimiter, fgets($fp,GRADE_CSV_LINE_LENGTH));
+ $header = explode($csv_delimiter, fgets($fp, GRADE_CSV_LINE_LENGTH));
// print some preview
$numlines = 0; // 0 preview lines displayed
}
echo '</tr>';
while (!feof ($fp) && $numlines <= $formdata->previewrows) {
- $lines = explode($csv_delimiter, fgets($fp,GRADE_CSV_LINE_LENGTH));
+ $lines = explode($csv_delimiter, fgets($fp, GRADE_CSV_LINE_LENGTH));
echo '<tr>';
foreach ($lines as $line) {
- echo '<td>'.$line.'</td>';;
+ echo '<td>'.$line.'</td>';
}
$numlines ++;
echo '</tr>';
$map = array();
// loops mapping_0, mapping_1 .. mapping_n and construct $map array
foreach ($header as $i => $head) {
- $map[$i] = $formdata->{'mapping_'.$i};
+ if (isset($formdata->{'mapping_'.$i})) {
+ $map[$i] = $formdata->{'mapping_'.$i};
+ }
}
// if mapping information is supplied
// check for mapto collisions
$maperrors = array();
- foreach ($map as $i=>$j) {
+ foreach ($map as $i => $j) {
if ($j == 0) {
// you can have multiple ignores
continue;
if ($fp = fopen($filename, "r")) {
// read the first line makes sure this doesn't get read again
- $header = explode($csv_delimiter, fgets($fp,GRADE_CSV_LINE_LENGTH));
+ $header = explode($csv_delimiter, fgets($fp, GRADE_CSV_LINE_LENGTH));
$newgradeitems = array(); // temporary array to keep track of what new headers are processed
$status = true;
while (!feof ($fp)) {
// add something
- $line = explode($csv_delimiter, fgets($fp,GRADE_CSV_LINE_LENGTH));
+ $line = explode($csv_delimiter, fgets($fp, GRADE_CSV_LINE_LENGTH));
if(count($line) <= 1){
// there is no data on this line, move on
$newgradeitem->importcode = $importcode;
$newgradeitem->importer = $USER->id;
- // failed to insert into new grade item buffer
+ // insert into new grade item buffer
$newgradeitems[$key] = $DB->insert_record('grade_import_newitem', $newgradeitem);
- // add this to grade_import_newitem table
- // add the new id to $newgradeitem[$key]
}
$newgrade = new stdClass();
$newgrade->newgradeitem = $newgradeitems[$key];
- $newgrade->finalgrade = $value;
- $newgrades[] = $newgrade;
- // if not, put it in
- // else, insert grade into the table
+ // if the user has a grade for this grade item
+ if (trim($value) != '-') {
+ // instead of omitting the grade we could insert one with finalgrade set to 0
+ // we do not have access to grade item min grade
+ $newgrade->finalgrade = $value;
+ $newgrades[] = $newgrade;
+ }
break;
case 'feedback':
if ($t1) {
global $CFG, $DB;
$relatedctxcondition = get_related_contexts_string(get_context_instance(CONTEXT_COURSE, $courseid));
- list($usql, $params) = $DB->get_in_or_equal(explode(',', $CFG->gradebookroles));
+ //users with a gradeable role
+ list($gradebookrolessql, $gradebookrolesparams) = $DB->get_in_or_equal(explode(',', $CFG->gradebookroles), SQL_PARAMS_NAMED, 'grbr0');
+
+ //enrolled users
+ $context = get_context_instance(CONTEXT_COURSE, $courseid);
+ list($enrolledsql, $enrolledparams) = get_enrolled_sql($context);
$sql = "SELECT giv.id, u.firstname, u.lastname, u.idnumber AS useridnumber,
- COALESCE(gi.idnumber, gin.itemname) AS gradeidnumber
- FROM
- {grade_import_values} giv
- JOIN {user} u ON giv.userid = u.id
- LEFT JOIN {grade_items} gi ON gi.id = giv.itemid
- LEFT JOIN {grade_import_newitem} gin ON gin.id = giv.newgradeitem
- LEFT JOIN {role_assignments} ra ON (giv.userid = ra.userid AND
- ra.roleid $usql AND
- ra.contextid $relatedctxcondition)
- WHERE giv.importcode = ?
- AND ra.id IS NULL
- ORDER BY gradeidnumber, u.lastname, u.firstname";
- $params[] = $importcode;
+ COALESCE(gi.idnumber, gin.itemname) AS gradeidnumber
+ FROM {grade_import_values} giv
+ JOIN {user} u
+ ON giv.userid = u.id
+ LEFT JOIN {grade_items} gi
+ ON gi.id = giv.itemid
+ LEFT JOIN {grade_import_newitem} gin
+ ON gin.id = giv.newgradeitem
+ LEFT JOIN ($enrolledsql) je
+ ON je.id = u.id
+ LEFT JOIN {role_assignments} ra
+ ON (giv.userid = ra.userid AND ra.roleid $gradebookrolessql AND ra.contextid $relatedctxcondition)
+ WHERE giv.importcode = :importcode
+ AND (ra.id IS NULL OR je.id IS NULL)
+ ORDER BY gradeidnumber, u.lastname, u.firstname";
+ $params = array_merge($gradebookrolesparams, $enrolledparams);
+ $params['importcode'] = $importcode;
return $DB->get_records_sql($sql, $params);
}
public function load_users() {
global $CFG, $DB;
- list($usql, $gbrparams) = $DB->get_in_or_equal(explode(',', $this->gradebookroles), SQL_PARAMS_NAMED, 'grbr0');
+ //limit to users with a gradeable role
+ list($gradebookrolessql, $gradebookrolesparams) = $DB->get_in_or_equal(explode(',', $this->gradebookroles), SQL_PARAMS_NAMED, 'grbr0');
+ //limit to users with an active enrollment
+ list($enrolledsql, $enrolledparams) = get_enrolled_sql($this->context);
+
+ //fields we need from the user table
+ $userfields = user_picture::fields('u', array('idnumber'));
+
+ //if the user has clicked one of the sort asc/desc arrows
if (is_numeric($this->sortitemid)) {
- $params = array_merge(array('gitemid'=>$this->sortitemid), $gbrparams, $this->groupwheresql_params);
+ $params = array_merge(array('gitemid'=>$this->sortitemid), $gradebookrolesparams, $this->groupwheresql_params, $enrolledparams);
// the MAX() magic is required in order to please PG
$sort = "MAX(g.finalgrade) $this->sortorder";
- $ufields = user_picture::fields('u', array('idnumber'));
- $sql = "SELECT $ufields
+ $sql = "SELECT $userfields
FROM {user} u
- JOIN {role_assignments} ra ON ra.userid = u.id
- $this->groupsql
- LEFT JOIN {grade_grades} g ON (g.userid = u.id AND g.itemid = :gitemid)
- WHERE ra.roleid $usql AND u.deleted = 0
- $this->groupwheresql
+ JOIN ($enrolledsql) je
+ ON je.id = u.id
+ JOIN {role_assignments} ra
+ ON ra.userid = u.id
+ $this->groupsql
+ LEFT JOIN {grade_grades} g
+ ON (g.userid = u.id AND g.itemid = :gitemid)
+ WHERE ra.roleid $gradebookrolessql
+ AND u.deleted = 0
AND ra.contextid ".get_related_contexts_string($this->context)."
- GROUP BY $ufields
+ $this->groupwheresql
+ GROUP BY $userfields
ORDER BY $sort";
} else {
$sort = "u.idnumber $this->sortorder"; break;
}
- $params = array_merge($gbrparams, $this->groupwheresql_params);
+ $params = array_merge($gradebookrolesparams, $this->groupwheresql_params, $enrolledparams);
- $userfields = user_picture::fields('u', array('idnumber'));
$sql = "SELECT DISTINCT $userfields
FROM {user} u
- JOIN {role_assignments} ra ON u.id = ra.userid
+ JOIN ($enrolledsql) je
+ ON je.id = u.id
+ JOIN {role_assignments} ra
+ ON u.id = ra.userid
$this->groupsql
- WHERE ra.roleid $usql AND u.deleted = 0
- $this->groupwheresql
+ WHERE ra.roleid $gradebookrolessql
+ AND u.deleted = 0
AND ra.contextid ".get_related_contexts_string($this->context)."
+ $this->groupwheresql
ORDER BY $sort";
}
$totalcount = $this->get_numusers($grouponly);
- list($usql, $rolesparams) = $DB->get_in_or_equal(explode(',', $this->gradebookroles), SQL_PARAMS_NAMED, 'grbr0');
+ //limit to users with a gradeable role
+ list($gradebookrolessql, $gradebookrolesparams) = $DB->get_in_or_equal(explode(',', $this->gradebookroles), SQL_PARAMS_NAMED, 'grbr0');
+
+ //limit to users with an active enrollment
+ list($enrolledsql, $enrolledparams) = get_enrolled_sql($this->context);
if ($showaverages) {
- $params = array_merge(array('courseid'=>$this->courseid), $rolesparams, $groupwheresqlparams);
+ $params = array_merge(array('courseid'=>$this->courseid), $gradebookrolesparams, $enrolledparams, $groupwheresqlparams);
// find sums of all grade items in course
$SQL = "SELECT g.itemid, SUM(g.finalgrade) AS sum
FROM {grade_items} gi
- JOIN {grade_grades} g ON g.itemid = gi.id
- JOIN {user} u ON u.id = g.userid
- JOIN {role_assignments} ra ON ra.userid = u.id
- $groupsql
+ JOIN {grade_grades} g
+ ON g.itemid = gi.id
+ JOIN {user} u
+ ON u.id = g.userid
+ JOIN ($enrolledsql) je
+ ON je.id = u.id
+ JOIN {role_assignments} ra
+ ON ra.userid = u.id
+ $groupsql
WHERE gi.courseid = :courseid
- AND ra.roleid $usql
+ AND ra.roleid $gradebookrolessql
AND ra.contextid ".get_related_contexts_string($this->context)."
AND g.finalgrade IS NOT NULL
$groupwheresql
// MDL-10875 Empty grades must be evaluated as grademin, NOT always 0
// This query returns a count of ungraded grades (NULL finalgrade OR no matching record in grade_grades table)
- $params = array_merge(array('courseid'=>$this->courseid), $rolesparams, $groupwheresqlparams);
$SQL = "SELECT gi.id, COUNT(u.id) AS count
FROM {grade_items} gi
- CROSS JOIN {user} u
- JOIN {role_assignments} ra ON ra.userid = u.id
- LEFT OUTER JOIN {grade_grades} g ON (g.itemid = gi.id AND g.userid = u.id AND g.finalgrade IS NOT NULL)
- $groupsql
+ CROSS JOIN {user} u
+ JOIN ($enrolledsql) je
+ ON je.id = u.id
+ JOIN {role_assignments} ra
+ ON ra.userid = u.id
+ LEFT OUTER JOIN {grade_grades} g
+ ON (g.itemid = gi.id AND g.userid = u.id AND g.finalgrade IS NOT NULL)
+ $groupsql
WHERE gi.courseid = :courseid
- AND ra.roleid $usql
+ AND ra.roleid $gradebookrolessql
AND ra.contextid ".get_related_contexts_string($this->context)."
AND g.id IS NULL
$groupwheresql
$groupsql = "";
$groupwheresql = "";
- list($usql, $params) = $DB->get_in_or_equal(explode(',', $this->gradebookroles), SQL_PARAMS_NAMED, 'grbr0');
+
+ //limit to users with a gradeable role
+ list($gradebookrolessql, $gradebookrolesparams) = $DB->get_in_or_equal(explode(',', $this->gradebookroles), SQL_PARAMS_NAMED, 'grbr0');
+
+ //limit to users with an active enrollment
+ list($enrolledsql, $enrolledparams) = get_enrolled_sql($this->context);
+
+ $params = array_merge($gradebookrolesparams, $enrolledparams);
if ($groups) {
$groupsql = $this->groupsql;
$countsql = "SELECT COUNT(DISTINCT u.id)
FROM {user} u
- JOIN {role_assignments} ra ON u.id = ra.userid
- $groupsql
- WHERE ra.roleid $usql AND u.deleted = 0
+ JOIN ($enrolledsql) je
+ ON je.id = u.id
+ JOIN {role_assignments} ra
+ ON u.id = ra.userid
+ $groupsql
+ WHERE ra.roleid $gradebookrolessql
+ AND u.deleted = 0
$groupwheresql
AND ra.contextid ".get_related_contexts_string($this->context);
return $DB->count_records_sql($countsql, $params);
}
}
-echo $OUTPUT->footer();
\ No newline at end of file
+echo $OUTPUT->footer();
*/
public $table;
- var $gtree;
+ /**
+ * An array of table headers
+ * @var array
+ */
+ public $tableheaders = array();
+
+ /**
+ * An array of table columns
+ * @var array
+ */
+ public $tablecolumns = array();
+
+ /**
+ * An array containing rows of data for the table.
+ * @var type
+ */
+ public $tabledata = array();
+
+ /**
+ * The grade tree structure
+ * @var grade_tree
+ */
+ public $gtree;
/**
* Flat structure similar to grade tree
/**
* Show range
*/
- var $showrange;
+ public $showrange = true;
- var $tableheaders;
- var $tablecolumns;
+ /**
+ * Show grades in the report, default true
+ * @var bool
+ */
+ public $showgrade = true;
- var $maxdepth;
- var $evenodd;
+ /**
+ * Decimal points to use for values in the report, default 2
+ * @var int
+ */
+ public $decimals = 2;
- var $tabledata;
- var $canviewhidden;
+ /**
+ * The number of decimal places to round range to, default 0
+ * @var int
+ */
+ public $rangedecimals = 0;
- var $switch;
+ /**
+ * Show grade feedback in the report, default true
+ * @var bool
+ */
+ public $showfeedback = true;
+
+ /**
+ * Show grade weighting in the report, default false
+ * @var bool
+ */
+ public $showweight = false;
+
+ /**
+ * Show letter grades in the report, default false
+ * @var bool
+ */
+ public $showlettergrade = false;
+
+ /**
+ * Show average grades in the report, default false.
+ * @var false
+ */
+ public $showaverage = false;
+
+ public $maxdepth;
+ public $evenodd;
+
+ public $canviewhidden;
+
+ public $switch;
/**
* Show hidden items even when user does not have required cap
*/
public $showhiddenitems;
+ public $showtotalsifcontainhidden;
+
+ public $baseurl;
+ public $pbarurl;
/**
* Constructor. Sets local copies of user preferences and initialises grade_tree.
* @param int $userid The id of the user
*/
public function __construct($courseid, $gpr, $context, $userid) {
- global $CFG, $DB;
+ global $DB, $CFG;
parent::__construct($courseid, $gpr, $context);
$this->showrank = grade_get_setting($this->courseid, 'report_user_showrank', $CFG->grade_report_user_showrank);
$this->showhiddenitems = grade_get_setting($this->courseid, 'report_user_showhiddenitems', $CFG->grade_report_user_showhiddenitems);
$this->showtotalsifcontainhidden = grade_get_setting($this->courseid, 'report_user_showtotalsifcontainhidden', $CFG->grade_report_user_showtotalsifcontainhidden);
+ $this->showgrade = grade_get_setting($this->courseid, 'report_user_showgrade', !empty($CFG->grade_report_user_showgrade));
+ $this->showrange = grade_get_setting($this->courseid, 'report_user_showrange', !empty($CFG->grade_report_user_showrange));
+ $this->showfeedback = grade_get_setting($this->courseid, 'report_user_showfeedback', !empty($CFG->grade_report_user_showfeedback));
+ $this->showweight = grade_get_setting($this->courseid, 'report_user_showweight', !empty($CFG->grade_report_user_showweight));
+ $this->showlettergrade = grade_get_setting($this->courseid, 'report_user_showlettergrade', !empty($CFG->grade_report_user_showlettergrade));
+ $this->showaverage = grade_get_setting($this->courseid, 'report_user_showaverage', !empty($CFG->grade_report_user_showaverage));
+
+ // The default grade decimals is 2
+ $defaultdecimals = 2;
+ if (property_exists($CFG, 'grade_decimalpoints')) {
+ $defaultdecimals = $CFG->grade_decimalpoints;
+ }
+ $this->decimals = grade_get_setting($this->courseid, 'decimalpoints', $defaultdecimals);
+
+ // The default range decimals is 0
+ $defaultrangedecimals = 0;
+ if (property_exists($CFG, 'grade_report_user_rangedecimals')) {
+ $defaultrangedecimals = $CFG->grade_report_user_rangedecimals;
+ }
+ $this->rangedecimals = grade_get_setting($this->courseid, 'report_user_rangedecimals', $defaultrangedecimals);
+
$this->switch = grade_get_setting($this->courseid, 'aggregationposition', $CFG->grade_aggregationposition);
// Grab the grade_tree for this course
// no groups on this report - rank is from all course users
$this->setup_table();
+
+ //optionally calculate grade item averages
+ $this->calculate_averages();
}
function inject_rowspans(&$element) {
* Prepares the headers and attributes of the flexitable.
*/
public function setup_table() {
- global $CFG;
/*
- * Table has 5-6 columns
- *| itemname/description | final grade | percentage final grade | rank (optional) | feedback |
+ * Table has 1-8 columns
+ *| All columns except for itemname/description are optional
*/
// setting up table headers
- $this->tablecolumns = array('itemname', 'grade');
- $this->tableheaders = array($this->get_lang_string('gradeitem', 'grades'),
- $this->get_lang_string('grade'));
+
+ $this->tablecolumns = array('itemname');
+ $this->tableheaders = array($this->get_lang_string('gradeitem', 'grades'));
+
+ if ($this->showweight) {
+ $this->tablecolumns[] = 'weight';
+ $this->tableheaders[] = $this->get_lang_string('weightuc', 'grades');
+ }
+
+ if ($this->showgrade) {
+ $this->tablecolumns[] = 'grade';
+ $this->tableheaders[] = $this->get_lang_string('grade', 'grades');
+ }
if ($this->showrange) {
$this->tablecolumns[] = 'range';
$this->tableheaders[] = $this->get_lang_string('percentage', 'grades');
}
+ if ($this->showlettergrade) {
+ $this->tablecolumns[] = 'lettergrade';
+ $this->tableheaders[] = $this->get_lang_string('lettergrade', 'grades');
+ }
+
if ($this->showrank) {
- // TODO: this is broken if hidden grades present!!
$this->tablecolumns[] = 'rank';
$this->tableheaders[] = $this->get_lang_string('rank', 'grades');
}
- $this->tablecolumns[] = 'feedback';
- $this->tableheaders[] = $this->get_lang_string('feedback', 'grades');
+ if ($this->showaverage) {
+ $this->tablecolumns[] = 'average';
+ $this->tableheaders[] = $this->get_lang_string('average', 'grades');
+ }
+ if ($this->showfeedback) {
+ $this->tablecolumns[] = 'feedback';
+ $this->tableheaders[] = $this->get_lang_string('feedback', 'grades');
+ }
}
function fill_table() {
}
private function fill_table_recursive(&$element) {
- global $CFG, $DB;
+ global $DB, $CFG;
$type = $element['type'];
$depth = $element['depth'];
/// Actual Grade
$gradeval = $grade_grade->finalgrade;
- if ($grade_grade->grade_item->needsupdate) {
- $data['grade']['class'] = $class.' gradingerror';
- $data['grade']['content'] = get_string('error');
- } else if (!empty($CFG->grade_hiddenasdate) and $grade_grade->get_datesubmitted() and !$this->canviewhidden and $grade_grade->is_hidden()
- and !$grade_grade->grade_item->is_category_item() and !$grade_grade->grade_item->is_course_item()) {
- // the problem here is that we do not have the time when grade value was modified, 'timemodified' is general modification date for grade_grades records
- $class .= ' datesubmitted';
- $data['grade']['class'] = $class;
- $data['grade']['content'] = get_string('submittedon', 'grades', userdate($grade_grade->get_datesubmitted(), get_string('strftimedatetimeshort')));
-
- } elseif ($grade_grade->is_hidden()) {
- $data['grade']['class'] = $class.' hidden';
- $data['grade']['content'] = '-';
- } else {
- $data['grade']['class'] = $class;
- $gradeval = $this->blank_hidden_total($this->courseid, $grade_grade->grade_item, $gradeval);
- $data['grade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true);
+
+ $class .= " itemcenter ";
+ if ($this->showweight) {
+ $data['weight']['class'] = $class;
+ $data['weight']['content'] = '-';
+ // has a weight assigned, might be extra credit
+ if ($grade_object->aggregationcoef > 0 && $type <> 'courseitem') {
+ $data['weight']['content'] = number_format($grade_object->aggregationcoef,2).'%';
+ }
}
- /// Percentage
+ if ($this->showgrade) {
+ if ($grade_grade->grade_item->needsupdate) {
+ $data['grade']['class'] = $class.' gradingerror';
+ $data['grade']['content'] = get_string('error');
+ } else if (!empty($CFG->grade_hiddenasdate) and $grade_grade->get_datesubmitted() and !$this->canviewhidden and $grade_grade->is_hidden()
+ and !$grade_grade->grade_item->is_category_item() and !$grade_grade->grade_item->is_course_item()) {
+ // the problem here is that we do not have the time when grade value was modified, 'timemodified' is general modification date for grade_grades records
+ $class .= ' datesubmitted';
+ $data['grade']['class'] = $class;
+ $data['grade']['content'] = get_string('submittedon', 'grades', userdate($grade_grade->get_datesubmitted(), get_string('strftimedatetimeshort')));
+
+ } elseif ($grade_grade->is_hidden()) {
+ $data['grade']['class'] = $class.' hidden';
+ $data['grade']['content'] = '-';
+ } else {
+ $data['grade']['class'] = $class;
+ $gradeval = $this->blank_hidden_total($this->courseid, $grade_grade->grade_item, $gradeval);
+ $data['grade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true);
+ }
+ }
+
+ // Range
+ if ($this->showrange) {
+ $data['range']['class'] = $class;
+ $data['range']['content'] = $grade_grade->grade_item->get_formatted_range(GRADE_DISPLAY_TYPE_REAL, $this->rangedecimals);
+ }
+
+ // Percentage
if ($this->showpercentage) {
if ($grade_grade->grade_item->needsupdate) {
$data['percentage']['class'] = $class.' gradingerror';
$data['percentage']['content'] = get_string('error');
- } elseif ($grade_grade->is_hidden()) {
- $data['percentage']['class'] = $class.' hidden';
- $data['percentage']['content'] = '-';
+ } else if ($grade_grade->is_hidden()) {
+ $data['percentage']['class'] = $class.' hidden';
+ $data['percentage']['content'] = '-';
} else {
$data['percentage']['class'] = $class;
$data['percentage']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE);
}
}
- /// Rank
+ // Lettergrade
+ if ($this->showlettergrade) {
+ if ($grade_grade->grade_item->needsupdate) {
+ $data['lettergrade']['class'] = $class.' gradingerror';
+ $data['lettergrade']['content'] = get_string('error');
+ } else if ($grade_grade->is_hidden()) {
+ $data['lettergrade']['class'] = $class.' hidden';
+ if (!$this->canviewhidden) {
+ $data['lettergrade']['content'] = '-';
+ } else {
+ $data['lettergrade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_LETTER);
+ }
+ } else {
+ $data['lettergrade']['class'] = $class;
+ $data['lettergrade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_LETTER);
+ }
+ }
+
+ // Rank
if ($this->showrank) {
- // TODO: this is broken if hidden grades present!!
if ($grade_grade->grade_item->needsupdate) {
$data['rank']['class'] = $class.' gradingerror';
$data['rank']['content'] = get_string('error');
$sql = "SELECT COUNT(DISTINCT(userid))
FROM {grade_grades}
WHERE finalgrade > ?
- AND itemid = ?";
+ AND itemid = ?
+ AND hidden = 0";
$rank = $DB->count_records_sql($sql, array($grade_grade->finalgrade, $grade_grade->grade_item->id)) + 1;
$data['rank']['class'] = $class;
}
}
- /// Feedback
- if (empty($grade_grade->feedback) or (!$this->canviewhidden and $grade_grade->is_hidden())) {
- $data['feedback']['class'] = $class.' feedbacktext';
- $data['feedback']['content'] = ' ';
-
- } else {
- $data['feedback']['class'] = $class.' feedbacktext';
- $data['feedback']['content'] = format_text($grade_grade->feedback, $grade_grade->feedbackformat, array('overflowdiv'=>true));
+ // Average
+ if ($this->showaverage) {
+ $data['average']['class'] = $class;
+ if (!empty($this->gtree->items[$eid]->avg)) {
+ $data['average']['content'] = $this->gtree->items[$eid]->avg;
+ } else {
+ $data['average']['content'] = '-';
+ }
}
- /// Range
- if ($this->showrange) {
- $data['range']['class'] = $class;
- $data['range']['content'] = $grade_grade->grade_item->get_formatted_range();
+ // Feedback
+ if ($this->showfeedback) {
+ if ($grade_grade->overridden > 0 AND ($type == 'categoryitem' OR $type == 'courseitem')) {
+ $data['feedback']['class'] = $class.' feedbacktext';
+ $data['feedback']['content'] = get_string('overridden', 'grades').': ' . format_text($grade_grade->feedback, $grade_grade->feedbackformat);
+ } else if (empty($grade_grade->feedback) or (!$this->canviewhidden and $grade_grade->is_hidden())) {
+ $data['feedback']['class'] = $class.' feedbacktext';
+ $data['feedback']['content'] = ' ';
+ } else {
+ $data['feedback']['class'] = $class.' feedbacktext';
+ $data['feedback']['content'] = format_text($grade_grade->feedback, $grade_grade->feedbackformat);
+ }
}
}
}
}
function process_action($target, $action) {
}
+
+ /**
+ * Builds the grade item averages.
+ *
+ */
+ function calculate_averages() {
+ global $USER, $DB;
+
+ if ($this->showaverage) {
+ // this settings are actually grader report settings (not user report)
+ // however we're using them as having two separate but identical settings the
+ // user would have to keep in sync would be annoying
+ $averagesdisplaytype = $this->get_pref('averagesdisplaytype');
+ $averagesdecimalpoints = $this->get_pref('averagesdecimalpoints');
+ $meanselection = $this->get_pref('meanselection');
+ $shownumberofgrades = $this->get_pref('shownumberofgrades');
+
+ $avghtml = '';
+ $avgcssclass = 'avg';
+
+ $straverage = get_string('overallaverage', 'grades');
+
+ $groupsql = $this->groupsql;
+ $groupwheresql = $this->groupwheresql;
+ //$groupwheresqlparams = ;
+
+ if ($shownumberofgrades) {
+ $straverage .= ' (' . get_string('submissions', 'grades') . ') ';
+ }
+
+ $totalcount = $this->get_numusers(false);
+
+ //limit to users with a gradeable role ie students
+ list($gradebookrolessql, $gradebookrolesparams) = $DB->get_in_or_equal(explode(',', $this->gradebookroles), SQL_PARAMS_NAMED, 'grbr0');
+
+ //limit to users with an active enrolment
+ list($enrolledsql, $enrolledparams) = get_enrolled_sql($this->context);
+
+ $params = array_merge($this->groupwheresql_params, $gradebookrolesparams, $enrolledparams);
+ $params['courseid'] = $this->courseid;
+
+ // find sums of all grade items in course
+ $sql = "SELECT gg.itemid, SUM(gg.finalgrade) AS sum
+ FROM {grade_items} gi
+ JOIN {grade_grades} gg
+ ON gg.itemid = gi.id
+ JOIN ($enrolledsql) je
+ ON je.id = gg.userid
+ JOIN {role_assignments} ra
+ ON ra.userid = gg.userid
+ $groupsql
+ WHERE gi.courseid = :courseid
+ AND ra.roleid $gradebookrolessql
+ AND ra.contextid ".get_related_contexts_string($this->context)."
+ AND gg.finalgrade IS NOT NULL
+ AND gg.hidden = 0
+ $groupwheresql
+ GROUP BY gg.itemid";
+
+ $sum_array = array();
+ if ($sums = $DB->get_recordset_sql($sql, $params)) {
+ foreach ($sums as $itemid => $csum) {
+ $sum_array[$itemid] = $csum->sum;
+ }
+ $sums->close();
+ }
+
+ $columncount=0;
+
+ // Empty grades must be evaluated as grademin, NOT always 0
+ // This query returns a count of ungraded grades (NULL finalgrade OR no matching record in grade_grades table)
+ // No join condition when joining grade_items and user to get a grade item row for every user
+ // Then left join with grade_grades and look for rows with null final grade (which includes grade items with no grade_grade)
+ $sql = "SELECT gi.id, COUNT(u.id) AS count
+ FROM {grade_items} gi
+ JOIN {user} u
+ JOIN ($enrolledsql) je
+ ON je.id = u.id
+ JOIN {role_assignments} ra
+ ON ra.userid = u.id
+ LEFT JOIN {grade_grades} gg
+ ON (gg.itemid = gi.id AND gg.userid = u.id AND gg.finalgrade IS NOT NULL AND gg.hidden = 0)
+ $groupsql
+ WHERE gi.courseid = :courseid
+ AND ra.roleid $gradebookrolessql
+ AND ra.contextid ".get_related_contexts_string($this->context)."
+ AND gg.finalgrade IS NULL
+ $groupwheresql
+ GROUP BY gi.id";
+
+ $ungraded_counts = $DB->get_records_sql($sql, $params);
+
+ foreach ($this->gtree->items as $itemid=>$unused) {
+ if (!empty($this->gtree->items[$itemid]->avg)) {
+ continue;
+ }
+ $item = $this->gtree->items[$itemid];
+
+ if ($item->needsupdate) {
+ $avghtml .= '<td class="cell c' . $columncount++.'"><span class="gradingerror">'.get_string('error').'</span></td>';
+ continue;
+ }
+
+ if (empty($sum_array[$item->id])) {
+ $sum_array[$item->id] = 0;
+ }
+
+ if (empty($ungraded_counts[$itemid])) {
+ $ungraded_count = 0;
+ } else {
+ $ungraded_count = $ungraded_counts[$itemid]->count;
+ }
+
+ //do they want the averages to include all grade items
+ if ($meanselection == GRADE_REPORT_MEAN_GRADED) {
+ $mean_count = $totalcount - $ungraded_count;
+ } else { // Bump up the sum by the number of ungraded items * grademin
+ $sum_array[$item->id] += ($ungraded_count * $item->grademin);
+ $mean_count = $totalcount;
+ }
+
+ $decimalpoints = $item->get_decimals();
+
+ // Determine which display type to use for this average
+ if (!empty($USER->gradeediting) && $USER->gradeediting[$this->courseid]) {
+ $displaytype = GRADE_DISPLAY_TYPE_REAL;
+
+ } else if ($averagesdisplaytype == GRADE_REPORT_PREFERENCE_INHERIT) { // no ==0 here, please resave the report and user preferences
+ $displaytype = $item->get_displaytype();
+
+ } else {
+ $displaytype = $averagesdisplaytype;
+ }
+
+ // Override grade_item setting if a display preference (not inherit) was set for the averages
+ if ($averagesdecimalpoints == GRADE_REPORT_PREFERENCE_INHERIT) {
+ $decimalpoints = $item->get_decimals();
+
+ } else {
+ $decimalpoints = $averagesdecimalpoints;
+ }
+
+ if (empty($sum_array[$item->id]) || $mean_count == 0) {
+ $this->gtree->items[$itemid]->avg = '-';
+ } else {
+ $sum = $sum_array[$item->id];
+ $avgradeval = $sum/$mean_count;
+ $gradehtml = grade_format_gradevalue($avgradeval, $item, true, $displaytype, $decimalpoints);
+
+ $numberofgrades = '';
+ if ($shownumberofgrades) {
+ $numberofgrades = " ($mean_count)";
+ }
+
+ $this->gtree->items[$itemid]->avg = $gradehtml.$numberofgrades;
+ }
+ }
+ }
+ }
}
function grade_report_user_settings_definition(&$mform) {
$mform->addElement('select', 'report_user_showpercentage', get_string('showpercentage', 'grades'), $options);
$mform->addHelpButton('report_user_showpercentage', 'showpercentage', 'grades');
+ if (empty($CFG->grade_report_user_showgrade)) {
+ $options[-1] = get_string('defaultprev', 'grades', $options[0]);
+ } else {
+ $options[-1] = get_string('defaultprev', 'grades', $options[1]);
+ }
+
+ $mform->addElement('select', 'report_user_showgrade', get_string('showgrade', 'grades'), $options);
+
+ if (empty($CFG->grade_report_user_showfeedback)) {
+ $options[-1] = get_string('defaultprev', 'grades', $options[0]);
+ } else {
+ $options[-1] = get_string('defaultprev', 'grades', $options[1]);
+ }
+
+ $mform->addElement('select', 'report_user_showfeedback', get_string('showfeedback', 'grades'), $options);
+
+ if (empty($CFG->grade_report_user_showweight)) {
+ $options[-1] = get_string('defaultprev', 'grades', $options[0]);
+ } else {
+ $options[-1] = get_string('defaultprev', 'grades', $options[1]);
+ }
+
+ $mform->addElement('select', 'report_user_showweight', get_string('showweight', 'grades'), $options);
+
+ if (empty($CFG->grade_report_user_showaverage)) {
+ $options[-1] = get_string('defaultprev', 'grades', $options[0]);
+ } else {
+ $options[-1] = get_string('defaultprev', 'grades', $options[1]);
+ }
+
+ $mform->addElement('select', 'report_user_showaverage', get_string('showaverage', 'grades'), $options);
+ $mform->addHelpButton('report_user_showaverage', 'showaverage', 'grades');
+
+ if (empty($CFG->grade_report_user_showlettergrade)) {
+ $options[-1] = get_string('defaultprev', 'grades', $options[0]);
+ } else {
+ $options[-1] = get_string('defaultprev', 'grades', $options[1]);
+ }
+
+ $mform->addElement('select', 'report_user_showlettergrade', get_string('showlettergrade', 'grades'), $options);
+
+ if (empty($CFG->grade_report_user_showrange)) {
+ $options[-1] = get_string('defaultprev', 'grades', $options[0]);
+ } else {
+ $options[-1] = get_string('defaultprev', 'grades', $options[1]);
+ }
+
+ $mform->addElement('select', 'report_user_showrange', get_string('showrange', 'grades'), $options);
+
+ $options = array(0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5);
+ if (! empty($CFG->grade_report_user_rangedecimals)) {
+ $options[-1] = $options[$CFG->grade_report_user_rangedecimals];
+ }
+ $mform->addElement('select', 'report_user_rangedecimals', get_string('rangedecimals', 'grades'), $options);
+
$options = array(-1 => get_string('default', 'grades'),
0 => get_string('shownohidden', 'grades'),
1 => get_string('showhiddenuntilonly', 'grades'),
if ($ADMIN->fulltree) {
- $settings->add(new admin_setting_configcheckbox('grade_report_user_showrank', get_string('showrank', 'grades'), get_string('showrank_help', 'grades'), 0, PARAM_INT));
- $settings->add(new admin_setting_configcheckbox('grade_report_user_showpercentage', get_string('showpercentage', 'grades'), get_string('showpercentage_help', 'grades'), 2, PARAM_INT));
+ $settings->add(new admin_setting_configcheckbox('grade_report_user_showrank', get_string('showrank', 'grades'), get_string('showrank_help', 'grades'), 0));
+ $settings->add(new admin_setting_configcheckbox('grade_report_user_showpercentage', get_string('showpercentage', 'grades'), get_string('showpercentage_help', 'grades'), 1));
+ $settings->add(new admin_setting_configcheckbox('grade_report_user_showgrade', get_string('showgrade', 'grades'), get_string('showgrade_help', 'grades'), 1));
+ $settings->add(new admin_setting_configcheckbox('grade_report_user_showfeedback', get_string('showfeedback', 'grades'), get_string('showfeedback_help', 'grades'), 1));
+ $settings->add(new admin_setting_configcheckbox('grade_report_user_showrange', get_string('showrange', 'grades'), get_string('showrange_help', 'grades'), 1));
+ $settings->add(new admin_setting_configcheckbox('grade_report_user_showweight', get_string('showweight', 'grades'), get_string('showweight_help', 'grades'), 0));
+ $settings->add(new admin_setting_configcheckbox('grade_report_user_showaverage', get_string('showaverage', 'grades'), get_string('showaverage_help', 'grades'), 0));
+ $settings->add(new admin_setting_configcheckbox('grade_report_user_showlettergrade', get_string('showlettergrade', 'grades'), get_string('showlettergrade_help', 'grades'), 0));
+ $settings->add(new admin_setting_configselect('grade_report_user_rangedecimals', get_string('rangedecimals', 'grades'),
+ get_string('rangedecimals_help', 'grades'), 0,array(0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5)));
$options = array(0 => get_string('shownohidden', 'grades'),
1 => get_string('showhiddenuntilonly', 'grades'),
.user-grade td.excluded {background-color: #666;}
.user-grade td.hidden {color: #aaa;}
.user-grade td.feedbacktext {max-width:600px;padding:0;}
-.pagelayout-report .user-grade .feedbacktext .no-overflow {overflow:auto;padding:0.25em;}
\ No newline at end of file
+.pagelayout-report .user-grade .feedbacktext .no-overflow {overflow:auto;padding:0.25em;}
+
+table.user-grade td.feedbacktext {text-align:left;width: 40%;font-size: 0.8em;white-space:normal;}
+table.user-grade td.itemcenter {text-align:center;}
\ No newline at end of file
$groupingname = format_string($grouping->name);
+navigation_node::override_active_url(new moodle_url('/group/index.php', array('id'=>$course->id)));
+$PAGE->set_pagelayout('standard');
+
$PAGE->navbar->add($strparticipants, new moodle_url('/user/index.php', array('id'=>$courseid)));
$PAGE->navbar->add($strgroups, new moodle_url('/group/index.php', array('id'=>$courseid)));
$PAGE->navbar->add($straddgroupstogroupings);
<p>Sistēmā Moodle tas vēlāk var izraisīt atmiņas izmantošanas problēmas, it īpaši tad,
ja būsit iespējojis lielu skaitu moduļu un/vai lietotāju.</p>
-<p>Ieteicams konfigurēt PHP ar pēc iespējas lielāku atmiņas apjomu, piemēram, 40 MB.
- Ir vairāki veidi, kā to var izdarīt, piemēram:</p>
+<p>Ja iespējams, ieteicams konfigurēt PHP ar lielāku maksimālās atmiņas apjomu, piemēram, 40 MB. Ir vairāki veidi, kā to var izdarīt, piemēram:</p>
<ol>
<li>Ja iespējams, atkārtoti kompilējiet PHP, izmantojot <i>--enable-memory-limit</i>.
Šādā gadījumā sistēma Moodle atmiņas apjoma ierobežojumu varēs iestatīt automātiski.</li>
-<li>Ja jums ir piekļuve php.ini failam, varat mainīt tajā esošo parametra <b>memory_limit</b>
- iestatījumu, piemēram, uz 40 MB. Ja jums nav piekļuves šim failam, palūdziet
- to izdarīt administratoram.</li>
-<li>Dažos PHP serveros Moodle direktorijā var izveidot failu .htaccess, kurā
- ir šāda rinda:
- <p><blockquote>php_value memory_limit 40M</blockquote></p>
+<li>Ja jums ir piekļuve php.ini failam, varat mainīt tajā esošo parametra <b>memory_limit</b> iestatījumu, piemēram, uz 40 MB. Ja jums nav piekļuves šim failam, palūdziet to izdarīt administratoram.</li>
+<li>Dažos PHP serveros Moodle direktorijā var izveidot failu .htaccess, kurā ir šāda rinda: <p><blockquote>php_value memory_limit 40M</blockquote></p>
<p>Tomēr dažos serveros tas neļaus darboties <b>nevienai</b> PHP lapai
- (atverot šīs lapas, tiks parādīti kļūdas ziņojumi), un fails .htaccess būs jānoņem.</p></li>
+(atverot šīs lapas, tiks parādīti kļūdas ziņojumi), un fails .htaccess būs jānoņem.</p></li>
</ol>';
$string['phpversion'] = 'PHP versija';
$string['phpversionhelp'] = '<p>Sistēmā Moodle jāizmanto PHP, kuras versija ir vismaz 4.3.0 vai 5.1.0 (versijai 5.0.x piemīt vairākas zināmas problēmas).</p>
$string['dbprefix'] = 'Prefixo das tabelas';
$string['dirroot'] = 'Diretório Moodle';
$string['environmenthead'] = 'Verificando o ambiente ...';
+$string['errorsinenvironment'] = 'Verificação do Ambiente falhou!';
$string['installation'] = 'Instalação';
$string['langdownloaderror'] = 'Infelizmente o idioma "{$a}" não foi instalado. A instalação vai continuar em Inglês.';
$string['memorylimithelp'] = '<p>O limite de memória do PHP configurado atualmente no seu servidor é de {$a}.</p>
<p><blockquote>php_value memory_limit 40M</blockquote></p>
<p>Alguns servidores não aceitam este procedimento e <b>todas</b> as páginas PHP do servidor ficam bloqueadas ou imprimem mensagens de erro. Neste caso será necessário excluir o arquivo .htaccess .</p>
</li></ol>';
+$string['pathssubdataroot'] = 'Você precisa de um local onde o Moodle possa salvar arquivos enviados. Este diretório deve possuir permissões de leitura e escrita pelo usuário do servidor web
+(geralmente \'nobody\' ou \'apache \'), mas não deverá ser acessível diretamente através da web. O instalador irá tentar criá-lo se ele não existir.';
$string['pathssubdirroot'] = 'Caminho completo do diretório para instalação do Moddle.';
$string['pathssubwwwroot'] = 'Endereço web completo onde o Moodle será acessado.
Não é possível acessar o Moodle usando múltiplos endereços. Se seu site tem múltiplos endereços públicos você deve configurar redirecionamentos permantentes em todos eles exceto esse. Se seu site é acessado tanto da Intranet como Internet, use o endereço público aqui e configure o DNS para que os usuários da Intranet possam usar o endereço público também. Se o endereço não estiver correto, por favo mude a URL no seu navegador para reiniciar a instalação com um valor diferente.';
$string['pathshead'] = 'பாதைகளை ஊர்ஜிதப்படுத்து';
$string['phpextension'] = '{$a} PHP நீட்சி';
$string['phpversion'] = 'PHP பதிப்பு';
-$string['phpversionhelp'] = '<p>Moodle குறைந்தளவு ஒரு PHP பதிப்பின் 4.3.0 or 5.1.0 ஐ (5.0.x அறியப்பட்ட பிரச்சினைகளின் ஒரு எண்ணிக்கையைக் கொண்டிருக்கின்றது) வேண்டுகின்றது).</p>
+$string['phpversionhelp'] = '<p>Moodle குறைந்தளவு ஒரு PHP பதிப்பின் 4.3.0 or 5.1.0 ஐ (5.0.x அறியப்பட்ட பிரச்சினைகளின் ஒரு எண்ணிக்கையைக் கொண்டிருக்கின்றது) வேண்டுகின்றது.</p>
<p>நீங்கள் தற்போதைய பதிப்பு {$a} ஐ இயக்குகின்றீர்கள்</p>
<p>நீங்கள் PHP ஐ மேம்படுத்த அல்லது PHP இன் ஒரு புதிய பதிப்புடன் ஒரு வழங்கியிற்கு நகர்த்த வேண்டும்!<br/>
$string['setting'] = 'Setting';
$string['settings'] = 'Settings';
$string['setweights'] = 'Set weights';
+$string['showaverage'] = 'Show average';
+$string['showaverage_help'] = 'Show the average column? Students may be able to estimate other student\'s grades if the average is calculated from a small number of grades. For performance reasons the average is approximate if it is dependent on any hidden items.';
+$string['showfeedback'] = 'Show feedback';
+$string['showfeedback_help'] = 'Show the feedback column?';
+$string['showgrade'] = 'Show grades';
+$string['showgrade_help'] = 'Show the grade column?';
+$string['showlettergrade'] = 'Show letter grades';
+$string['showlettergrade_help'] = 'Show the letter grade column?';
+$string['showrange'] = 'Show ranges';
+$string['showrange_help'] = 'Show the range column?';
+$string['showweight'] = 'Show weightings';
+$string['showweight_help'] = 'Show the grade weight column?';
+$string['rangedecimals'] = 'Range decimal points';
+$string['rangedecimals_help'] = 'The number of decimal points to display for range.';
$string['showactivityicons'] = 'Show activity icons';
$string['showactivityicons_help'] = 'If enabled, activity icons are shown next to activity names.';
$string['showallhidden'] = 'Show hidden';
$string['shownumberofgrades'] = 'Show number of grades in averages';
$string['shownumberofgrades_help'] = 'If enabled, the number of grades used when calculating the average (mean) is displayed in brackets after each average.';
$string['showpercentage'] = 'Show percentage';
-$string['showpercentage_help'] = 'This setting determines whether the percentage value of each grade item is shown.';
+$string['showpercentage_help'] = 'Show the percentage value of each grade item?';
$string['showquickfeedback'] = 'Show quick feedback';
$string['showquickfeedback_help'] = 'If enabled, when editing is turned on, a feedback text input box with a dotted border appears for each grade, allowing the feedback for many grades to be edited at the same time. Changes are saved and highlighted when the update button is clicked.
$string['showranges'] = 'Show ranges';
$string['showranges_help'] = 'If enabled, the grader report will contain an additional row displaying the range for each category and grade item.';
$string['showrank'] = 'Show rank';
-$string['showrank_help'] = 'This setting determines whether the position of the student in relation to the rest of the class is shown for each grade item.';
+$string['showrank_help'] = 'Show the position of the student in relation to the rest of the class for each grade item?';
$string['showuseridnumber'] = 'Show user ID numbers';
$string['showuseridnumber_help'] = 'If enabled, user ID numbers are shown in an additional column.';
$string['showuserimage'] = 'Show user profile images';
$navigation = new global_navigation_for_ajax($PAGE, $branchtype, $branchid);
$linkcategories = false;
-
+
if ($instanceid!==null) {
// Get the db record for the block instance
$blockrecord = $DB->get_record('block_instances', array('id'=>$instanceid,'blockname'=>'navigation'));
$block->trim($navigation, $trimmode, $trimlength, ceil($trimlength/2));
}
$converter = new navigation_json();
-
+
// Find the actuall branch we are looking for
$branch = $navigation->find($branchid, $branchtype);
-
+
// Remove links to categories if required.
if (!$linkcategories) {
foreach ($branch->find_all_of_type(navigation_node::TYPE_CATEGORY) as $category) {
$category->action = null;
}
}
-
+
// Stop buffering errors at this point
$html = ob_get_contents();
ob_end_clean();
// Prepare an XML converter for the branch
$converter->set_expandable($navigation->get_expandable());
// Set XML headers
-header('Content-type: text/plain');
+header('Content-type: text/plain; charset=utf-8');
// Convert and output the branch as XML
echo $converter->convert($branch);
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
- 'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
)
),
<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="lib/db" VERSION="20101121" COMMENT="XMLDB file for core Moodle tables"
+<XMLDB PATH="lib/db" VERSION="20110114" COMMENT="XMLDB file for core Moodle tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
>
<TABLE NAME="message" COMMENT="Stores all unread messages" PREVIOUS="log_display" NEXT="message_read">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="useridfrom"/>
- <FIELD NAME="useridfrom" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="useridto"/>
- <FIELD NAME="useridto" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="useridfrom" NEXT="subject"/>
+ <FIELD NAME="useridfrom" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="useridto"/>
+ <FIELD NAME="useridto" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="useridfrom" NEXT="subject"/>
<FIELD NAME="subject" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" COMMENT="The message subject" PREVIOUS="useridto" NEXT="fullmessage"/>
<FIELD NAME="fullmessage" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" PREVIOUS="subject" NEXT="fullmessageformat"/>
<FIELD NAME="fullmessageformat" TYPE="int" LENGTH="4" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the full message" PREVIOUS="fullmessage" NEXT="fullmessagehtml"/>
<TABLE NAME="message_read" COMMENT="Stores all messages that have been read" PREVIOUS="message" NEXT="message_contacts">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="useridfrom"/>
- <FIELD NAME="useridfrom" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="useridto"/>
- <FIELD NAME="useridto" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="useridfrom" NEXT="subject"/>
+ <FIELD NAME="useridfrom" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="useridto"/>
+ <FIELD NAME="useridto" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="useridfrom" NEXT="subject"/>
<FIELD NAME="subject" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" COMMENT="The message subject" PREVIOUS="useridto" NEXT="fullmessage"/>
<FIELD NAME="fullmessage" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" PREVIOUS="subject" NEXT="fullmessageformat"/>
<FIELD NAME="fullmessageformat" TYPE="int" LENGTH="4" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the full message" PREVIOUS="fullmessage" NEXT="fullmessagehtml"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="timecreated"/>
</FIELDS>
<KEYS>
- <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+ <KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="contextid"/>
+ <KEY NAME="contextid" TYPE="foreign" FIELDS="contextid" REFTABLE="context" REFFIELDS="id" COMMENT="Relates to context.id" PREVIOUS="primary" NEXT="userid"/>
+ <KEY NAME="userid" TYPE="foreign" FIELDS="userid" REFTABLE="user" REFFIELDS="id" COMMENT="Relates to user.id" PREVIOUS="contextid"/>
</KEYS>
+ <INDEXES>
+ <INDEX NAME="itemid" UNIQUE="false" FIELDS="itemid"/>
+ </INDEXES>
</TABLE>
<TABLE NAME="license" COMMENT="store licenses used by moodle" PREVIOUS="rating" NEXT="registration_hubs">
<FIELDS>
</KEYS>
</TABLE>
</TABLES>
-</XMLDB>
+</XMLDB>
\ No newline at end of file
// add field
$field = new xmldb_field('tiuserid');
if (!$dbman->field_exists($table, $field)) {
- $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'itemid');
+ $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, 'itemid');
$dbman->add_field($table, $field);
}
// modify index
if ($oldversion < 2008081500) {
/// Changing the type of all the columns that the question bank uses to store grades to be NUMBER(12, 7).
$table = new xmldb_table('question');
- $field = new xmldb_field('defaultgrade', XMLDB_TYPE_NUMBER, '12, 7', null, null, null, null, 'generalfeedback');
+ $field = new xmldb_field('defaultgrade', XMLDB_TYPE_NUMBER, '12, 7', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '1.0000000', 'generalfeedback');
$dbman->change_field_type($table, $field);
upgrade_main_savepoint(true, 2008081500);
}
if ($oldversion < 2008081501) {
$table = new xmldb_table('question');
- $field = new xmldb_field('penalty', XMLDB_TYPE_NUMBER, '12, 7', null, null, null, null, 'defaultgrade');
+ $field = new xmldb_field('penalty', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0.1000000', 'defaultgrade');
$dbman->change_field_type($table, $field);
upgrade_main_savepoint(true, 2008081501);
}
if ($oldversion < 2008081502) {
$table = new xmldb_table('question_answers');
- $field = new xmldb_field('fraction', XMLDB_TYPE_NUMBER, '12, 7', null, null, null, null, 'answer');
+ $field = new xmldb_field('fraction', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'answer');
$dbman->change_field_type($table, $field);
upgrade_main_savepoint(true, 2008081502);
}
if ($oldversion < 2008081503) {
$table = new xmldb_table('question_sessions');
- $field = new xmldb_field('sumpenalty', XMLDB_TYPE_NUMBER, '12, 7', null, null, null, null, 'newgraded');
+ $field = new xmldb_field('sumpenalty', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'newgraded');
$dbman->change_field_type($table, $field);
upgrade_main_savepoint(true, 2008081503);
}
if ($oldversion < 2008081504) {
$table = new xmldb_table('question_states');
- $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '12, 7', null, null, null, null, 'event');
+ $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'event');
$dbman->change_field_type($table, $field);
upgrade_main_savepoint(true, 2008081504);
}
if ($oldversion < 2008081505) {
$table = new xmldb_table('question_states');
- $field = new xmldb_field('raw_grade', XMLDB_TYPE_NUMBER, '12, 7', null, null, null, null, 'grade');
+ $field = new xmldb_field('raw_grade', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'grade');
$dbman->change_field_type($table, $field);
upgrade_main_savepoint(true, 2008081505);
}
if ($oldversion < 2008081506) {
$table = new xmldb_table('question_states');
- $field = new xmldb_field('penalty', XMLDB_TYPE_NUMBER, '12, 7', null, null, null, null, 'raw_grade');
+ $field = new xmldb_field('penalty', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'raw_grade');
$dbman->change_field_type($table, $field);
upgrade_main_savepoint(true, 2008081506);
}
$table = new xmldb_table('block_instances');
/// Rename field weight on table block_instances to defaultweight
- $field = new xmldb_field('weight', XMLDB_TYPE_INTEGER, '3', null, XMLDB_NOTNULL, null, '0', 'position');
+ $field = new xmldb_field('weight', XMLDB_TYPE_INTEGER, 10, null, XMLDB_NOTNULL, null, null, 'position');
$dbman->rename_field($table, $field, 'defaultweight');
/// Rename field position on table block_instances to defaultregion
/// Adding fields to table block_positions
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
- $table->add_field('blockinstanceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
+ $table->add_field('blockinstanceid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
$table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
$table->add_field('pagetype', XMLDB_TYPE_CHAR, '64', null, XMLDB_NOTNULL, null, null);
$table->add_field('subpage', XMLDB_TYPE_CHAR, '16', null, XMLDB_NOTNULL, null, null);
- $table->add_field('visible', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '1');
+ $table->add_field('visible', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null);
$table->add_field('region', XMLDB_TYPE_CHAR, '16', null, XMLDB_NOTNULL, null, null);
$table->add_field('weight', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
if ($oldversion < 2009110400) {
// list of tables where we need to add new format field and convert texts
- $extendtables = array('course' => 'summary',
- 'course_categories' => 'description',
- 'course_categories' => 'description',
- 'course_request' => 'summary',
- 'grade_outcomes' => 'description',
- 'groups' => 'description',
- 'groupings' => 'description',
- 'scale' => 'description',
- 'user_info_field' => 'description',
- 'user_info_field' => 'defaultdata',
- 'user_info_data' => 'data');
-
- foreach ($extendtables as $tablestr=>$fieldstr) {
+ $extendtables = array('course' => 'summary',
+ 'course_categories' => 'description',
+ 'course_categories' => 'description',
+ 'course_request' => 'summary',
+ 'grade_outcomes' => 'description',
+ 'groups' => 'description',
+ 'groupings' => 'description',
+ 'scale' => 'description',
+ 'user_info_field' => 'description',
+ 'user_info_field' => 'defaultdata',
+ 'user_info_data' => 'data');
+
+ foreach ($extendtables as $tablestr => $fieldstr) {
$formatfieldstr = $fieldstr.'format';
$table = new xmldb_table($tablestr);
$dbman->add_field($table, $field);
}
if ($CFG->texteditors !== 'textarea') {
- $rs = $DB->get_recordset($tablestr, array($formatfieldstr=>FORMAT_MOODLE), '', "id,$fieldstr,$formatfieldstr");
+ $rs = $DB->get_recordset($tablestr, array($formatfieldstr => FORMAT_MOODLE), '', "id,$fieldstr,$formatfieldstr");
foreach ($rs as $rec) {
$rec->$fieldstr = text_to_html($rec->$fieldstr, false, false, true);
$rec->$formatfieldstr = FORMAT_HTML;
upgrade_set_timeout();
}
$rs->close();
+ unset($rs);
}
}
if ($oldversion < 2010011200) {
$table = new xmldb_table('grade_categories');
- $field = new xmldb_field('hidden', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0);
+ $field = new xmldb_field('hidden', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'timemodified');
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$table->add_field('userid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, 0);
$table->add_field('name', XMLDB_TYPE_CHAR, '200', null, XMLDB_NOTNULL, null, null);
- $table->add_field('private', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0);
- $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
+ $table->add_field('private', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '1');
+ $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '6', null, XMLDB_NOTNULL, null, '0');
/// Adding keys to table my_pages
//install.xml so there are 2.0 sites that are missing it.
if ($oldversion < 2010101900) {
$table = new xmldb_table('grade_categories');
- $field = new xmldb_field('hidden', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0);
+ $field = new xmldb_field('hidden', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'timemodified');
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
//MDL-24771
if ($oldversion < 2010102601) {
- $fieldnotification = new xmldb_field('notification', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'smallmessage');
- $fieldcontexturl = new xmldb_field('contexturl', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'notification');
- $fieldcontexturlname = new xmldb_field('contexturlname', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'contexturl');
+ $fieldnotification = new xmldb_field('notification', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, null, null, 0, 'smallmessage');
+ $fieldcontexturl = new xmldb_field('contexturl', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'notification');
+ $fieldcontexturlname = new xmldb_field('contexturlname', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'contexturl');
$fieldstoadd = array($fieldnotification, $fieldcontexturl, $fieldcontexturlname);
$tablestomodify = array(new xmldb_table('message'), new xmldb_table('message_read'));
if ($oldversion < 2010102700) {
$table = new xmldb_table('post');
- $field = new xmldb_field('uniquehash', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'content');
+ $field = new xmldb_field('uniquehash', XMLDB_TYPE_CHAR, '128', null, XMLDB_NOTNULL, null, null, 'content');
// Launch change of precision for field name
$dbman->change_field_precision($table, $field);
upgrade_main_savepoint(true, 2010121401);
}
+ if ($oldversion < 2011011401) {
+ $columns = $DB->get_columns('block_instances');
+
+ // Check if we need to fix the default weight column
+ if (array_key_exists('defaultweight', $columns) && $columns['defaultweight']->max_length != 10) {
+ // Fix discrepancies in the block_instances table after upgrade from 1.9
+ $table = new xmldb_table('block_instances');
+
+ // defaultweight is smallint(3) after upgrade should be bigint 10
+ // Also fixed in earlier upgrade code
+ $field = new xmldb_field('defaultweight', XMLDB_TYPE_INTEGER, 10, null, XMLDB_NOTNULL, null, null, 'defaultregion');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_type($table, $field);
+ }
+
+ // add missing key `blocinst_par_ix` (`parentcontextid`)
+ $index = new xmldb_index('parentcontextid', XMLDB_INDEX_NOTUNIQUE, array('parentcontextid'));
+ if (!$dbman->index_exists($table, $index)) {
+ $dbman->add_index($table, $index);
+ }
+ }
+
+ // Main savepoint reached
+ upgrade_main_savepoint(true, 2011011401);
+ }
+
+ if ($oldversion < 2011011402) {
+ // Fix discrepancies in the block_positions table after upgrade from 1.9
+ $table = new xmldb_table('block_positions');
+ $columns = $DB->get_columns('block_positions');
+
+ // Check if we need to fix the blockinstanceid field
+ if (array_key_exists('blockinstanceid', $columns) && empty($columns['blockinstanceid']->unsigned)) {
+ // Fix blockinstanceid
+ // First remove the indexs on the field
+ $indexone = new xmldb_index('blockinstanceid', XMLDB_INDEX_NOTUNIQUE, array('blockinstanceid'));
+ $indexall = new xmldb_index('blockinstanceid-contextid-pagetype-subpage', XMLDB_INDEX_UNIQUE, array('blockinstanceid','contextid','pagetype','subpage'));
+ if ($dbman->index_exists($table, $indexone)) {
+ $dbman->drop_index($table, $indexone);
+ }
+ if ($dbman->index_exists($table, $indexall)) {
+ $dbman->drop_index($table, $indexall);
+ }
+ // blockinstanceid should be unsigned
+ // Also fixed in earlier upgrade code
+ $field = new xmldb_field('blockinstanceid', XMLDB_TYPE_INTEGER, 10, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, 'id');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_unsigned($table, $field);
+ }
+
+ // Add the indexs back in
+ $dbman->add_index($table, $indexone);
+ $dbman->add_index($table, $indexall);
+ }
+
+ // Check if the visible field needs fixing.
+ if (array_key_exists('visible', $columns) && !empty($columns['visible']->has_default)) {
+ // visible shouldn't have a default
+ // Also fixed in earlier upgrade code
+ $field = new xmldb_field('visible', XMLDB_TYPE_INTEGER, 4, null, XMLDB_NOTNULL, null, null, 'subpage');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_default($table, $field);
+ }
+ }
+
+ // Main savepoint reached
+ upgrade_main_savepoint(true, 2011011402);
+ }
+
+ if ($oldversion < 2011011403) {
+ $columns = $DB->get_columns('grade_categories');
+ // Check if we need to fix the hidden field
+ if (array_key_exists('hidden', $columns) && $columns['hidden']->max_length != 1) {
+ // Fix discrepancies in the grade_categories table after upgrade from 1.9
+ $table = new xmldb_table('grade_categories');
+
+ // hidden should be tinyint(1)
+ // Also fixed in earlier upgrade code
+ $field = new xmldb_field('hidden', XMLDB_TYPE_INTEGER, 1, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'timemodified');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_precision($table, $field);
+ }
+ }
+
+ // Main savepoint reached
+ upgrade_main_savepoint(true, 2011011403);
+ }
+
+ if ($oldversion < 2011011404) {
+ // Fix discrepancies in the message table after upgrade from 1.9
+ $columns = $DB->get_columns('message');
+ $table = new xmldb_table('message');
+
+ // Check if we need to fix the useridfrom field
+ if (array_key_exists('useridfrom', $columns) && empty($columns['useridfrom']->unsigned)) {
+ // useridfrom should be unsigned
+ $field = new xmldb_field('useridfrom', XMLDB_TYPE_INTEGER, 10, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'id');
+ $index = new xmldb_index('useridfrom', XMLDB_INDEX_NOTUNIQUE, array('useridfrom'));
+ if ($dbman->index_exists($table, $index)) {
+ $dbman->drop_index($table, $index);
+ }
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_unsigned($table, $field);
+ }
+ $dbman->add_index($table, $index);
+ }
+
+ // Check if we need to fix the useridto field
+ if (array_key_exists('useridto', $columns) && empty($columns['useridto']->unsigned)) {
+ // useridto should be unsigned
+ $field = new xmldb_field('useridto', XMLDB_TYPE_INTEGER, 10, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'useridfrom');
+ $index = new xmldb_index('useridto', XMLDB_INDEX_NOTUNIQUE, array('useridto'));
+ if ($dbman->index_exists($table, $index)) {
+ $dbman->drop_index($table, $index);
+ }
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_unsigned($table, $field);
+ }
+ $dbman->add_index($table, $index);
+ }
+
+ // Check if we need to fix the notification field
+ if (array_key_exists('notification', $columns) && !empty($columns['notification']->not_null)) {
+ // notification should allow null
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('notification', XMLDB_TYPE_INTEGER, 1, XMLDB_UNSIGNED, null, null, 0, 'smallmessage');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_notnull($table, $field);
+ }
+ }
+
+ // Check if we need to fix the contexturl field
+ if (array_key_exists('contexturl', $columns) && strpos($columns['contexturl']->type, 'text') === false) {
+ // contexturl should be text
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('contexturl', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'notification');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_type($table, $field);
+ }
+ }
+
+ // Check if we need to fix the contexturl field
+ if (array_key_exists('contexturlname', $columns) && strpos($columns['contexturlname']->type, 'text') === false) {
+ // contexturlname should be text
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('contexturlname', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'contexturl');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_type($table, $field);
+ }
+ }
+
+ // Main savepoint reached
+ upgrade_main_savepoint(true, 2011011404);
+ }
+
+ if ($oldversion < 2011011405) {
+ // Fix discrepancies in the message_read table after upgrade from 1.9
+ $columns = $DB->get_columns('message_read');
+ $table = new xmldb_table('message_read');
+
+ // Check if we need to fix the useridfrom field
+ if (array_key_exists('useridfrom', $columns) && empty($columns['useridfrom']->unsigned)) {
+ // useridfrom should be unsigned
+ $field = new xmldb_field('useridfrom', XMLDB_TYPE_INTEGER, 10, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'id');
+ $index = new xmldb_index('useridfrom', XMLDB_INDEX_NOTUNIQUE, array('useridfrom'));
+ if ($dbman->index_exists($table, $index)) {
+ $dbman->drop_index($table, $index);
+ }
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_unsigned($table, $field);
+ }
+ $dbman->add_index($table, $index);
+ }
+
+ // Check if we need to fix the useridto field
+ if (array_key_exists('useridto', $columns) && empty($columns['useridto']->unsigned)) {
+ // useridto should be unsigned
+ $field = new xmldb_field('useridto', XMLDB_TYPE_INTEGER, 10, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'useridfrom');
+ $index = new xmldb_index('useridto', XMLDB_INDEX_NOTUNIQUE, array('useridto'));
+ if ($dbman->index_exists($table, $index)) {
+ $dbman->drop_index($table, $index);
+ }
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_unsigned($table, $field);
+ }
+ $dbman->add_index($table, $index);
+ }
+
+ // Check if we need to fix the notification field
+ if (array_key_exists('notification', $columns) && !empty($columns['notification']->not_null)) {
+ // notification should allow null
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('notification', XMLDB_TYPE_INTEGER, 1, XMLDB_UNSIGNED, null, null, 0, 'smallmessage');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_notnull($table, $field);
+ }
+ }
+
+ // Check if we need to fix the contexturl field
+ if (array_key_exists('contexturl', $columns) && strpos($columns['contexturl']->type, 'text') === false) {
+ // contexturl should be text
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('contexturl', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'notification');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_type($table, $field);
+ }
+ }
+
+ // Check if we need to fix the contexturl field
+ if (array_key_exists('contexturlname', $columns) && strpos($columns['contexturlname']->type, 'text') === false) {
+ // contexturlname should be text
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('contexturlname', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'contexturl');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_type($table, $field);
+ }
+ }
+
+ // Main savepoint reached
+ upgrade_main_savepoint(true, 2011011405);
+ }
+
+ if ($oldversion < 2011011406) {
+ // Fix discrepancies in the my_pages table after upgrade from 1.9
+ $columns = $DB->get_columns('my_pages');
+ $table = new xmldb_table('my_pages');
+
+ // Check if we need to fix the private column
+ if (array_key_exists('private', $columns) && $columns['private']->default_value != '1') {
+ // private should be default 1
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('private', XMLDB_TYPE_INTEGER, 1, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 1, 'name');
+ $index = new xmldb_index('user_idx', XMLDB_INDEX_NOTUNIQUE, array('userid','private'));
+ if ($dbman->index_exists($table, $index)) {
+ $dbman->drop_index($table, $index);
+ }
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_default($table, $field);
+ }
+ $dbman->add_index($table, $index);
+ }
+
+ // Check if we need to fix the sortorder field
+ if (array_key_exists('sortorder', $columns) && !empty($columns['sortorder']->unsigned)) {
+ // Sortorder should not be unsigned
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('sortorder', XMLDB_TYPE_INTEGER, 6, null, XMLDB_NOTNULL, null, 0, 'private');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_notnull($table, $field);
+ }
+ }
+
+ upgrade_main_savepoint(true, 2011011406);
+ }
+
+ if ($oldversion < 2011011407) {
+ // Check if we need to fix post.uniquehash
+ $columns = $DB->get_columns('my_pages');
+ if (array_key_exists('uniquehash', $columns) && $columns['uniquehash']->max_length != 128) {
+ // Fix discrepancies in the post table after upgrade from 1.9
+ $table = new xmldb_table('post');
+
+ // Uniquehash should be 128 chars
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('uniquehash', XMLDB_TYPE_CHAR, 128, null, XMLDB_NOTNULL, null, null, 'content');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_precision($table, $field);
+ }
+ }
+
+ upgrade_main_savepoint(true, 2011011407);
+ }
+
+ if ($oldversion < 2011011408) {
+ // Fix question in the post table after upgrade from 1.9
+ $columns = $DB->get_columns('question');
+ $table = new xmldb_table('question');
+
+ // Check if we need to fix default grade
+ if (array_key_exists('defaultgrade', $columns) && (
+ empty($columns['defaultgrade']->unsigned) ||
+ empty($columns['defaultgrade']->not_null) ||
+ $columns['defaultgrade']->default_value !== '1.0000000')) {
+ // defaultgrade should be unsigned NOT NULL DEFAULT '1.0000000'
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('defaultgrade', XMLDB_TYPE_NUMBER, '12, 7', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '1.0000000', 'generalfeedbackformat');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_default($table, $field);
+ }
+ }
+
+ // Check if we need to fix penalty
+ if (array_key_exists('penalty', $columns) && (empty($columns['penalty']->not_null) || $columns['penalty']->default_value !== '0.1000000')) {
+ // penalty should be NOT NULL DEFAULT '0.1000000'
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('penalty', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0.1000000', 'defaultgrade');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_default($table, $field);
+ }
+ }
+
+ upgrade_main_savepoint(true, 2011011408);
+ }
+
+ if ($oldversion < 2011011409) {
+ // Fix question_answers in the post table after upgrade from 1.9
+ $columns = $DB->get_columns('question_answers');
+ $table = new xmldb_table('question_answers');
+
+ if (array_key_exists('fraction', $columns) && empty($columns['fraction']->not_null)) {
+ // fraction should be NOT NULL DEFAULT '0.0000000',
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('fraction', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'feedback');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_default($table, $field);
+ }
+ }
+
+ upgrade_main_savepoint(true, 2011011409);
+ }
+
+ if ($oldversion < 2011011410) {
+ // Fix question_sessions in the post table after upgrade from 1.9
+ $columns = $DB->get_columns('question_sessions');
+ $table = new xmldb_table('question_sessions');
+
+ // Check if we need to fix sumpenalty
+ if (array_key_exists('sumpenalty', $columns) && empty($columns['sumpenalty']->not_null)) {
+ // sumpenalty should be NOT NULL DEFAULT '0.0000000',
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('sumpenalty', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'newgraded');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_default($table, $field);
+ }
+ }
+
+ upgrade_main_savepoint(true, 2011011410);
+ }
+
+ if ($oldversion < 2011011411) {
+ // Fix question_states in the post table after upgrade from 1.9
+ $columns = $DB->get_columns('question_states');
+ $table = new xmldb_table('question_states');
+
+ // Check if we need to fix grade
+ if (array_key_exists('grade', $columns) && empty($columns['grade']->not_null)) {
+ // grade should be NOT NULL DEFAULT '0.0000000',
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'event');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_default($table, $field);
+ }
+ }
+
+ // Check if we need to fix raw_grade
+ if (array_key_exists('raw_grade', $columns) && empty($columns['raw_grade']->not_null)) {
+ // raw_grade should be NOT NULL DEFAULT '0.0000000',
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('raw_grade', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'grade');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_default($table, $field);
+ }
+ }
+
+ // Check if we need to fix raw_grade
+ if (array_key_exists('penalty', $columns) && empty($columns['penalty']->not_null)) {
+ // penalty should be NOT NULL DEFAULT '0.0000000',
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('penalty', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'raw_grade');
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_default($table, $field);
+ }
+ }
+
+ upgrade_main_savepoint(true, 2011011411);
+ }
+
+ if ($oldversion < 2011011412) {
+ // Fix tag_instance in the post table after upgrade from 1.9
+ $columns = $DB->get_columns('tag_instance');
+ $table = new xmldb_table('tag_instance');
+
+ // Check if we need to fix tiuserid
+ if (array_key_exists('tiuserid', $columns) && !empty($columns['tiuserid']->has_default)) {
+ // tiuserid should have no default
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('tiuserid', XMLDB_TYPE_INTEGER, 10, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, 'itemid');
+ $index = new xmldb_index('itemtype-itemid-tagid-tiuserid', XMLDB_INDEX_UNIQUE, array('itemtype', 'itemid', 'tagid', 'tiuserid'));
+ if ($dbman->index_exists($table, $index)) {
+ $dbman->drop_index($table, $index);
+ }
+ if ($dbman->field_exists($table, $field)) {
+ $dbman->change_field_default($table, $field);
+ }
+ $dbman->add_index($table, $index);
+ }
+
+ upgrade_main_savepoint(true, 2011011412);
+ }
+
+ if ($oldversion < 2011011413) {
+ // Fix user_info_field in the post table after upgrade from 1.9
+ $table = new xmldb_table('user_info_field');
+
+ // Missing field descriptionformat
+ // Fixed in earlier upgrade code
+ $field = new xmldb_field('descriptionformat', XMLDB_TYPE_INTEGER, 2, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'description');
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+
+ upgrade_main_savepoint(true, 2011011413);
+ }
+
+ if ($oldversion < 2011011414) {
+ // Drop the adodb_logsql table if it exists... it was never actually used anyway.
+ $table = new xmldb_table('adodb_logsql');
+
+ if ($dbman->table_exists($table)) {
+ $dbman->drop_table($table);
+ }
+
+ upgrade_main_savepoint(true, 2011011414);
+ }
+
+ if ($oldversion < 2011011415) {
+ //create the rating table indexes if required
+ $table = new xmldb_table('rating');
+
+ $index = new xmldb_index('itemid', XMLDB_INDEX_NOTUNIQUE, array('itemid'));
+ if (!$dbman->index_exists($table, $index)) {
+ $dbman->add_index($table, $index);
+
+ $key = new xmldb_key('contextid', XMLDB_KEY_FOREIGN, array('contextid'), 'context', array('id'));
+ $dbman->add_key($table, $key);
+
+ $key = new xmldb_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
+ $dbman->add_key($table, $key);
+ }
+
+ upgrade_main_savepoint(true, 2011011415);
+ }
+
return true;
}
}
$this->store_settings($dbhost, $dbuser, $dbpass, $dbname, $prefix, $dboptions);
- unset($this->dboptions['dbsocket']);
+ // dbsocket is used ONLY if host is NULL or 'localhost',
+ // you can not disable it because it is always tried if dbhost is 'localhost'
+ if (!empty($this->dboptions['dbsocket']) and strpos($this->dboptions['dbsocket'], '/') !== false) {
+ $dbsocket = $this->dboptions['dbsocket'];
+ } else {
+ $dbsocket = ini_get('mysqli.default_socket');
+ }
if (empty($this->dboptions['dbport'])) {
$dbport = ini_get('mysqli.default_port');
} else {
$dbport = (int)$this->dboptions['dbport'];
}
ob_start();
- $this->mysqli = new mysqli($dbhost, $dbuser, $dbpass, $dbname, $dbport);
+ $this->mysqli = new mysqli($dbhost, $dbuser, $dbpass, $dbname, $dbport, $dbsocket);
$dberr = ob_get_contents();
ob_end_clean();
$errorno = @$this->mysqli->connect_errno;
// Unix socket connections should have lower overhead
if (!empty($this->dboptions['dbsocket']) and ($this->dbhost === 'localhost' or $this->dbhost === '127.0.0.1')) {
$connection = "user='$this->dbuser' password='$pass' dbname='$this->dbname'";
+ if (strpos($this->dboptions['dbsocket'], '/') !== false) {
+ $connection = $connection." host='".$this->dboptions['dbsocket']."'";
+ }
} else {
- $this->dboptions['dbsocket'] = 0;
+ $this->dboptions['dbsocket'] = '';
if (empty($this->dbname)) {
// probably old style socket connection - do not add port
$port = "";
if (empty($CFG->xmlstrictheaders) and (!empty($options['legacy']) or !empty($options['noclean']) or !empty($options['trusted']))) {
// now deal somehow with non-standard tags, people scream when we do not make moodle code xtml strict,
// but they scream even more when we strip all tags that are not strict :-(
- $params['valid_elements'] = '*[*]';
+ $params['valid_elements'] = 'script[src|type],*[*]'; // for some reason the *[*] does not inlcude javascript src attribute MDL-25836
$params['invalid_elements'] = '';
}
$result = new environment_results('php_setting');
$result->setStatus(false);
$result->setErrorCode(NO_VERSION_DATA_FOUND);
- return $result;
+ $results[] = $result;
+ return $results;
}
/// Extract the php_setting part
}
case PARAM_TAG:
- //as long as magic_quotes_gpc is used, a backslash will be a
- //problem, so remove *all* backslash.
- //$param = str_replace('\\', '', $param);
- //remove some nasties
+ // Please note it is not safe to use the tag name directly anywhere,
+ // it must be processed with s(), urlencode() before embedding anywhere.
+ // remove some nasties
$param = preg_replace('~[[:cntrl:]]|[<>`]~u', '', $param);
//convert many whitespace chars into one
$param = preg_replace('/\s+/', ' ', $param);
$param = $textlib->substr(trim($param), 0, TAG_MAX_LENGTH);
return $param;
-
case PARAM_TAGLIST:
$tags = explode(',', $param);
$result = array();
return $cache[$course->id];
}
+ if (!property_exists($course, 'modinfo')) {
+ debugging('Coding problem - missing course modinfo property in get_fast_modinfo() call');
+ }
+
if (empty($course->modinfo)) {
// no modinfo yet - load it
rebuild_course_cache($course->id);
foreach (self::$fields as $field) {
if ($field === 'id') {
- if (isset($record->{$idalias})) {
+ if (property_exists($record, $idalias)) {
$return->id = $record->{$idalias};
}
} else {
- if (isset($record->{$fieldprefix.$field})) {
+ if (property_exists($record, $fieldprefix.$field)) {
$return->{$field} = $record->{$fieldprefix.$field};
}
}
// add extra fields if not already there
if ($extrafields) {
foreach ($extrafields as $e) {
- if ($e === 'id' or isset($return->{$e})) {
+ if ($e === 'id' or property_exists($return, $e)) {
continue;
}
$return->{$e} = $record->{$fieldprefix.$e};
$attributes['name'] = $name;
+ if (!empty($attributes['disabled'])) {
+ $attributes['disabled'] = 'disabled';
+ } else {
+ unset($attributes['disabled']);
+ }
+
$output = '';
foreach ($options as $value=>$label) {
if (is_array($label)) {
$output .= html_writer::empty_tag('link', array('rel' => 'alternate',
'type' => $type, 'title' => $alt->title, 'href' => $alt->url));
}
-
+
if (!empty($CFG->additionalhtmlhead)) {
$output .= "\n".$CFG->additionalhtmlhead;
}
public function header() {
// unfortunately YUI iframe upload does not support application/json
if (!empty($_FILES)) {
- @header('Content-type: text/plain');
+ @header('Content-type: text/plain; charset=utf-8');
} else {
- @header('Content-type: application/json');
+ @header('Content-type: application/json; charset=utf-8');
}
/// Headers to make it not cacheable and json
$DB->delete_records('sessions', array('sid'=>$user->sid));
}
$rs->close();
+
+ $purgebefore = time() - $maxlifetime;
+ // delete expired sessions for guest user account
+ $DB->delete_records_select('sessions', 'userid = ? AND timemodified < ?', array($CFG->siteguest, $purgebefore));
+ // delete expired sessions for userid = 0 (not logged in)
+ $DB->delete_records_select('sessions', 'userid = 0 AND timemodified < ?', array($purgebefore));
} catch (dml_exception $ex) {
error_log('Error gc-ing sessions');
}
// Detect CLI maintenance mode - this is useful when you need to mess with database, such as during upgrades
if (file_exists("$CFG->dataroot/climaintenance.html")) {
if (!CLI_SCRIPT) {
- header('Content-type: text/html');
+ header('Content-type: text/html; charset=utf-8');
/// Headers to make it not cacheable and json
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
$e->stacktrace = format_backtrace($backtrace, true);
}
}
- @header('Content-Type: application/json');
+ @header('Content-Type: application/json; charset=utf-8');
echo json_encode($e);
return;
}
--- /dev/null
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
+
+/**
+ * Unit tests for /lib/componentlib.class.php.
+ *
+ * @package moodlecore
+ * @copyright 2011 Tomasz Muras
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
+}
+require_once($CFG->libdir.'/componentlib.class.php');
+
+class componentlib_test extends UnitTestCase {
+
+ public function test_component_installer() {
+ global $CFG;
+
+ $ci = new component_installer('http://download.moodle.org', 'unittest', 'downloadtests.zip');
+ $this->assertTrue($ci->check_requisites());
+
+ $destpath = $CFG->dataroot.'/downloadtests';
+
+ //carefully remove component files to enforce fresh installation
+ @unlink($destpath.'/'.'downloadtests.md5');
+ @unlink($destpath.'/'.'test.html');
+ @unlink($destpath.'/'.'test.jpg');
+ @rmdir($destpath);
+
+ $this->assertEqual(COMPONENT_NEEDUPDATE, $ci->need_upgrade());
+
+ $status = $ci->install();
+ $this->assertEqual(COMPONENT_INSTALLED, $status);
+ $this->assertEqual('9e94f74b3efb1ff6cf075dc6b2abf15c', $ci->get_component_md5());
+
+ //it's already installed, so Moodle should detect it's up to date
+ $this->assertEqual(COMPONENT_UPTODATE, $ci->need_upgrade());
+ $status = $ci->install();
+ $this->assertEqual(COMPONENT_UPTODATE, $status);
+
+ //check if correct files were downloaded
+ $this->assertEqual('2af180e813dc3f446a9bb7b6af87ce24', md5_file($destpath.'/'.'test.jpg'));
+ $this->assertEqual('47250a973d1b88d9445f94db4ef2c97a', md5_file($destpath.'/'.'test.html'));
+
+ }
+}
$postdata = format_postdata_for_curlcall($postdatatoconvert);
$this->assertEqual($postdata, $expectedresult);
}
+
+ public function test_download_file_content() {
+ $testhtml = "http://download.moodle.org/unittest/test.html";
+ $contents = download_file_content($testhtml);
+ $this->assertEqual('47250a973d1b88d9445f94db4ef2c97a', md5($contents));
+ }
}
}
$this->assertEqual($returned->custom1, 'Value of custom1');
}
+
+ public function test_user_picture_fields_unaliasing_null() {
+ $fields = user_picture::fields();
+ $fields = array_map('trim', explode(',', $fields));
+
+ $fakerecord = new stdClass();
+ $fakerecord->aliasedid = 42;
+ foreach ($fields as $field) {
+ if ($field !== 'id') {
+ $fakerecord->{'prefix'.$field} = "Value of $field";
+ }
+ }
+ $fakerecord->prefixcustom1 = 'Value of custom1';
+ $fakerecord->prefiximagealt = null;
+
+ $returned = user_picture::unalias($fakerecord, array('custom1'), 'aliasedid', 'prefix');
+
+ $this->assertEqual($returned->id, 42);
+ $this->assertEqual($returned->imagealt, null);
+ foreach ($fields as $field) {
+ if ($field !== 'id' and $field !== 'imagealt') {
+ $this->assertEqual($returned->{$field}, "Value of $field");
+ }
+ }
+ $this->assertEqual($returned->custom1, 'Value of custom1');
+ }
}
// OK
} else if (is_null($value) && is_null($actual->$key)) {
// OK
+ } else if (!isset($actual->$key)) {
+ $mismatches[] = $key . ' (expected [' . $value . '] but was missing.';
} else {
$mismatches[] = $key . ' (expected [' . $value . '] got [' . $actual->$key . '].';
}
+++ /dev/null
-/*
-Copyright (c) 2010, Yahoo! Inc. All rights reserved.
-Code licensed under the BSD License:
-http://developer.yahoo.com/yui/license.html
-version: 2.8.1
-*/
-(function() {
-
-var Y = YAHOO.util;
-
-/*
-Copyright (c) 2006, Yahoo! Inc. All rights reserved.
-Code licensed under the BSD License:
-http://developer.yahoo.net/yui/license.txt
-*/
-
-/**
- * The animation module provides allows effects to be added to HTMLElements.
- * @module animation
- * @requires yahoo, event, dom
- */
-
-/**
- *
- * Base animation class that provides the interface for building animated effects.
- * <p>Usage: var myAnim = new YAHOO.util.Anim(el, { width: { from: 10, to: 100 } }, 1, YAHOO.util.Easing.easeOut);</p>
- * @class Anim
- * @namespace YAHOO.util
- * @requires YAHOO.util.AnimMgr
- * @requires YAHOO.util.Easing
- * @requires YAHOO.util.Dom
- * @requires YAHOO.util.Event
- * @requires YAHOO.util.CustomEvent
- * @constructor
- * @param {String | HTMLElement} el Reference to the element that will be animated
- * @param {Object} attributes The attribute(s) to be animated.
- * Each attribute is an object with at minimum a "to" or "by" member defined.
- * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
- * All attribute names use camelCase.
- * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
- * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
- */
-
-var Anim = function(el, attributes, duration, method) {
- if (!el) {
- YAHOO.log('element required to create Anim instance', 'error', 'Anim');
- }
- this.init(el, attributes, duration, method);
-};
-
-Anim.NAME = 'Anim';
-
-Anim.prototype = {
- /**
- * Provides a readable name for the Anim instance.
- * @method toString
- * @return {String}
- */
- toString: function() {
- var el = this.getEl() || {};
- var id = el.id || el.tagName;
- return (this.constructor.NAME + ': ' + id);
- },
-
- patterns: { // cached for performance
- noNegatives: /width|height|opacity|padding/i, // keep at zero or above
- offsetAttribute: /^((width|height)|(top|left))$/, // use offsetValue as default
- defaultUnit: /width|height|top$|bottom$|left$|right$/i, // use 'px' by default
- offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i // IE may return these, so convert these to offset
- },
-
- /**
- * Returns the value computed by the animation's "method".
- * @method doMethod
- * @param {String} attr The name of the attribute.
- * @param {Number} start The value this attribute should start from for this animation.
- * @param {Number} end The value this attribute should end at for this animation.
- * @return {Number} The Value to be applied to the attribute.
- */
- doMethod: function(attr, start, end) {
- return this.method(this.currentFrame, start, end - start, this.totalFrames);
- },
-
- /**
- * Applies a value to an attribute.
- * @method setAttribute
- * @param {String} attr The name of the attribute.
- * @param {Number} val The value to be applied to the attribute.
- * @param {String} unit The unit ('px', '%', etc.) of the value.
- */
- setAttribute: function(attr, val, unit) {
- var el = this.getEl();
- if ( this.patterns.noNegatives.test(attr) ) {
- val = (val > 0) ? val : 0;
- }
-
- if (attr in el && !('style' in el && attr in el.style)) {
- el[attr] = val;
- } else {
- Y.Dom.setStyle(el, attr, val + unit);
- }
- },
-
- /**
- * Returns current value of the attribute.
- * @method getAttribute
- * @param {String} attr The name of the attribute.
- * @return {Number} val The current value of the attribute.
- */
- getAttribute: function(attr) {
- var el = this.getEl();
- var val = Y.Dom.getStyle(el, attr);
-
- if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
- return parseFloat(val);
- }
-
- var a = this.patterns.offsetAttribute.exec(attr) || [];
- var pos = !!( a[3] ); // top or left
- var box = !!( a[2] ); // width or height
-
- if ('style' in el) {
- // use offsets for width/height and abs pos top/left
- if ( box || (Y.Dom.getStyle(el, 'position') == 'absolute' && pos) ) {
- val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
- } else { // default to zero for other 'auto'
- val = 0;
- }
- } else if (attr in el) {
- val = el[attr];
- }
-
- return val;
- },
-
- /**
- * Returns the unit to use when none is supplied.
- * @method getDefaultUnit
- * @param {attr} attr The name of the attribute.
- * @return {String} The default unit to be used.
- */
- getDefaultUnit: function(attr) {
- if ( this.patterns.defaultUnit.test(attr) ) {
- return 'px';
- }
-
- return '';
- },
-
- /**
- * Sets the actual values to be used during the animation. Should only be needed for subclass use.
- * @method setRuntimeAttribute
- * @param {Object} attr The attribute object
- * @private
- */
- setRuntimeAttribute: function(attr) {
- var start;
- var end;
- var attributes = this.attributes;
-
- this.runtimeAttributes[attr] = {};
-
- var isset = function(prop) {
- return (typeof prop !== 'undefined');
- };
-
- if ( !isset(attributes[attr]['to']) && !isset(attributes[attr]['by']) ) {
- return false; // note return; nothing to animate to
- }
-
- start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
-
- // To beats by, per SMIL 2.1 spec
- if ( isset(attributes[attr]['to']) ) {
- end = attributes[attr]['to'];
- } else if ( isset(attributes[attr]['by']) ) {
- if (start.constructor == Array) {
- end = [];
- for (var i = 0, len = start.length; i < len; ++i) {
- end[i] = start[i] + attributes[attr]['by'][i] * 1; // times 1 to cast "by"
- }
- } else {
- end = start + attributes[attr]['by'] * 1;
- }
- }
-
- this.runtimeAttributes[attr].start = start;
- this.runtimeAttributes[attr].end = end;
-
- // set units if needed
- this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ?
- attributes[attr]['unit'] : this.getDefaultUnit(attr);
- return true;
- },
-
- /**
- * Constructor for Anim instance.
- * @method init
- * @param {String | HTMLElement} el Reference to the element that will be animated
- * @param {Object} attributes The attribute(s) to be animated.
- * Each attribute is an object with at minimum a "to" or "by" member defined.
- * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
- * All attribute names use camelCase.
- * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
- * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
- */
- init: function(el, attributes, duration, method) {
- /**
- * Whether or not the animation is running.
- * @property isAnimated
- * @private
- * @type Boolean
- */
- var isAnimated = false;
-
- /**
- * A Date object that is created when the animation begins.
- * @property startTime
- * @private
- * @type Date
- */
- var startTime = null;
-
- /**
- * The number of frames this animation was able to execute.
- * @property actualFrames
- * @private
- * @type Int
- */
- var actualFrames = 0;
-
- /**
- * The element to be animated.
- * @property el
- * @private
- * @type HTMLElement
- */
- el = Y.Dom.get(el);
-
- /**
- * The collection of attributes to be animated.
- * Each attribute must have at least a "to" or "by" defined in order to animate.
- * If "to" is supplied, the animation will end with the attribute at that value.
- * If "by" is supplied, the animation will end at that value plus its starting value.
- * If both are supplied, "to" is used, and "by" is ignored.
- * Optional additional member include "from" (the value the attribute should start animating from, defaults to current value), and "unit" (the units to apply to the values).
- * @property attributes
- * @type Object
- */
- this.attributes = attributes || {};
-
- /**
- * The length of the animation. Defaults to "1" (second).
- * @property duration
- * @type Number
- */
- this.duration = !YAHOO.lang.isUndefined(duration) ? duration : 1;
-
- /**
- * The method that will provide values to the attribute(s) during the animation.
- * Defaults to "YAHOO.util.Easing.easeNone".
- * @property method
- * @type Function
- */
- this.method = method || Y.Easing.easeNone;
-
- /**
- * Whether or not the duration should be treated as seconds.
- * Defaults to true.
- * @property useSeconds
- * @type Boolean
- */
- this.useSeconds = true; // default to seconds
-
- /**
- * The location of the current animation on the timeline.
- * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
- * @property currentFrame
- * @type Int
- */
- this.currentFrame = 0;
-
- /**
- * The total number of frames to be executed.
- * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
- * @property totalFrames
- * @type Int
- */
- this.totalFrames = Y.AnimMgr.fps;
-
- /**
- * Changes the animated element
- * @method setEl
- */
- this.setEl = function(element) {
- el = Y.Dom.get(element);
- };
-
- /**
- * Returns a reference to the animated element.
- * @method getEl
- * @return {HTMLElement}
- */
- this.getEl = function() { return el; };
-
- /**
- * Checks whether the element is currently animated.
- * @method isAnimated
- * @return {Boolean} current value of isAnimated.
- */
- this.isAnimated = function() {
- return isAnimated;
- };
-
- /**
- * Returns the animation start time.
- * @method getStartTime
- * @return {Date} current value of startTime.
- */
- this.getStartTime = function() {
- return startTime;
- };
-
- this.runtimeAttributes = {};
-
- var logger = {};
- logger.log = function() {YAHOO.log.apply(window, arguments)};
-
- logger.log('creating new instance of ' + this);
-
- /**
- * Starts the animation by registering it with the animation manager.
- * @method animate
- */
- this.animate = function() {
- if ( this.isAnimated() ) {
- return false;
- }
-
- this.currentFrame = 0;
-
- this.totalFrames = ( this.useSeconds ) ? Math.ceil(Y.AnimMgr.fps * this.duration) : this.duration;
-
- if (this.duration === 0 && this.useSeconds) { // jump to last frame if zero second duration
- this.totalFrames = 1;
- }
- Y.AnimMgr.registerElement(this);
- return true;
- };
-
- /**
- * Stops the animation. Normally called by AnimMgr when animation completes.
- * @method stop
- * @param {Boolean} finish (optional) If true, animation will jump to final frame.
- */
- this.stop = function(finish) {
- if (!this.isAnimated()) { // nothing to stop
- return false;
- }
-
- if (finish) {
- this.currentFrame = this.totalFrames;
- this._onTween.fire();
- }
- Y.AnimMgr.stop(this);
- };
-
- var onStart = function() {
- this.onStart.fire();
-
- this.runtimeAttributes = {};
- for (var attr in this.attributes) {
- this.setRuntimeAttribute(attr);
- }
-
- isAnimated = true;
- actualFrames = 0;
- startTime = new Date();
- };
-
- /**
- * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s).
- * @private
- */
-
- var onTween = function() {
- var data = {
- duration: new Date() - this.getStartTime(),
- currentFrame: this.currentFrame
- };
-
- data.toString = function() {
- return (
- 'duration: ' + data.duration +
- ', currentFrame: ' + data.currentFrame
- );
- };
-
- this.onTween.fire(data);
-
- var runtimeAttributes = this.runtimeAttributes;
-
- for (var attr in runtimeAttributes) {
- this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
- }
-
- actualFrames += 1;
- };
-
- var onComplete = function() {
- var actual_duration = (new Date() - startTime) / 1000 ;
-
- var data = {
- duration: actual_duration,
- frames: actualFrames,
- fps: actualFrames / actual_duration
- };
-
- data.toString = function() {
- return (
- 'duration: ' + data.duration +
- ', frames: ' + data.frames +
- ', fps: ' + data.fps
- );
- };
-
- isAnimated = false;
- actualFrames = 0;
- this.onComplete.fire(data);
- };
-
- /**
- * Custom event that fires after onStart, useful in subclassing
- * @private
- */
- this._onStart = new Y.CustomEvent('_start', this, true);
-
- /**
- * Custom event that fires when animation begins
- * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction)
- * @event onStart
- */
- this.onStart = new Y.CustomEvent('start', this);
-
- /**
- * Custom event that fires between each frame
- * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction)
- * @event onTween
- */
- this.onTween = new Y.CustomEvent('tween', this);
-
- /**
- * Custom event that fires after onTween
- * @private
- */
- this._onTween = new Y.CustomEvent('_tween', this, true);
-
- /**
- * Custom event that fires when animation ends
- * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction)
- * @event onComplete
- */
- this.onComplete = new Y.CustomEvent('complete', this);
- /**
- * Custom event that fires after onComplete
- * @private
- */
- this._onComplete = new Y.CustomEvent('_complete', this, true);
-
- this._onStart.subscribe(onStart);
- this._onTween.subscribe(onTween);
- this._onComplete.subscribe(onComplete);
- }
-};
-
- Y.Anim = Anim;
-})();
-/**
- * Handles animation queueing and threading.
- * Used by Anim and subclasses.
- * @class AnimMgr
- * @namespace YAHOO.util
- */
-YAHOO.util.AnimMgr = new function() {
- /**
- * Reference to the animation Interval.
- * @property thread
- * @private
- * @type Int
- */
- var thread = null;
-
- /**
- * The current queue of registered animation objects.
- * @property queue
- * @private
- * @type Array
- */
- var queue = [];
-
- /**
- * The number of active animations.
- * @property tweenCount
- * @private
- * @type Int
- */
- var tweenCount = 0;
-
- /**
- * Base frame rate (frames per second).
- * Arbitrarily high for better x-browser calibration (slower browsers drop more frames).
- * @property fps
- * @type Int
- *
- */
- this.fps = 1000;
-
- /**
- * Interval delay in milliseconds, defaults to fastest possible.
- * @property delay
- * @type Int
- *
- */
- this.delay = 1;
-
- /**
- * Adds an animation instance to the animation queue.
- * All animation instances must be registered in order to animate.
- * @method registerElement
- * @param {object} tween The Anim instance to be be registered
- */
- this.registerElement = function(tween) {
- queue[queue.length] = tween;
- tweenCount += 1;
- tween._onStart.fire();
- this.start();
- };
-
- /**
- * removes an animation instance from the animation queue.
- * All animation instances must be registered in order to animate.
- * @method unRegister
- * @param {object} tween The Anim instance to be be registered
- * @param {Int} index The index of the Anim instance
- * @private
- */
- this.unRegister = function(tween, index) {
- index = index || getIndex(tween);
- if (!tween.isAnimated() || index === -1) {
- return false;
- }
-
- tween._onComplete.fire();
- queue.splice(index, 1);
-
- tweenCount -= 1;
- if (tweenCount <= 0) {
- this.stop();
- }
-
- return true;
- };
-
- /**
- * Starts the animation thread.
- * Only one thread can run at a time.
- * @method start
- */
- this.start = function() {
- if (thread === null) {
- thread = setInterval(this.run, this.delay);
- }
- };
-
- /**
- * Stops the animation thread or a specific animation instance.
- * @method stop
- * @param {object} tween A specific Anim instance to stop (optional)
- * If no instance given, Manager stops thread and all animations.
- */
- this.stop = function(tween) {
- if (!tween) {
- clearInterval(thread);
-
- for (var i = 0, len = queue.length; i < len; ++i) {
- this.unRegister(queue[0], 0);
- }
-
- queue = [];
- thread = null;
- tweenCount = 0;
- }
- else {
- this.unRegister(tween);
- }
- };
-
- /**
- * Called per Interval to handle each animation frame.
- * @method run
- */
- this.run = function() {
- for (var i = 0, len = queue.length; i < len; ++i) {
- var tween = queue[i];
- if ( !tween || !tween.isAnimated() ) { continue; }
-
- if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
- {
- tween.currentFrame += 1;
-
- if (tween.useSeconds) {
- correctFrame(tween);
- }
- tween._onTween.fire();
- }
- else { YAHOO.util.AnimMgr.stop(tween, i); }
- }
- };
-
- var getIndex = function(anim) {
- for (var i = 0, len = queue.length; i < len; ++i) {
- if (queue[i] === anim) {
- return i; // note return;
- }
- }
- return -1;
- };
-
- /**
- * On the fly frame correction to keep animation on time.
- * @method correctFrame
- * @private
- * @param {Object} tween The Anim instance being corrected.
- */
- var correctFrame = function(tween) {
- var frames = tween.totalFrames;
- var frame = tween.currentFrame;
- var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
- var elapsed = (new Date() - tween.getStartTime());
- var tweak = 0;
-
- if (elapsed < tween.duration * 1000) { // check if falling behind
- tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
- } else { // went over duration, so jump to end
- tweak = frames - (frame + 1);
- }
- if (tweak > 0 && isFinite(tweak)) { // adjust if needed
- if (tween.currentFrame + tweak >= frames) {// dont go past last frame
- tweak = frames - (frame + 1);
- }
-
- tween.currentFrame += tweak;
- }
- };
- this._queue = queue;
- this._getIndex = getIndex;
-};
-/**
- * Used to calculate Bezier splines for any number of control points.
- * @class Bezier
- * @namespace YAHOO.util
- *
- */
-YAHOO.util.Bezier = new function() {
- /**
- * Get the current position of the animated element based on t.
- * Each point is an array of "x" and "y" values (0 = x, 1 = y)
- * At least 2 points are required (start and end).
- * First point is start. Last point is end.
- * Additional control points are optional.
- * @method getPosition
- * @param {Array} points An array containing Bezier points
- * @param {Number} t A number between 0 and 1 which is the basis for determining current position
- * @return {Array} An array containing int x and y member data
- */
- this.getPosition = function(points, t) {
- var n = points.length;
- var tmp = [];
-
- for (var i = 0; i < n; ++i){
- tmp[i] = [points[i][0], points[i][1]]; // save input
- }
-
- for (var j = 1; j < n; ++j) {
- for (i = 0; i < n - j; ++i) {
- tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
- tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
- }
- }
-
- return [ tmp[0][0], tmp[0][1] ];
-
- };
-};
-(function() {
-/**
- * Anim subclass for color transitions.
- * <p>Usage: <code>var myAnim = new Y.ColorAnim(el, { backgroundColor: { from: '#FF0000', to: '#FFFFFF' } }, 1, Y.Easing.easeOut);</code> Color values can be specified with either 112233, #112233,
- * [255,255,255], or rgb(255,255,255)</p>
- * @class ColorAnim
- * @namespace YAHOO.util
- * @requires YAHOO.util.Anim
- * @requires YAHOO.util.AnimMgr
- * @requires YAHOO.util.Easing
- * @requires YAHOO.util.Bezier
- * @requires YAHOO.util.Dom
- * @requires YAHOO.util.Event
- * @constructor
- * @extends YAHOO.util.Anim
- * @param {HTMLElement | String} el Reference to the element that will be animated
- * @param {Object} attributes The attribute(s) to be animated.
- * Each attribute is an object with at minimum a "to" or "by" member defined.
- * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
- * All attribute names use camelCase.
- * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
- * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
- */
- var ColorAnim = function(el, attributes, duration, method) {
- ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
- };
-
- ColorAnim.NAME = 'ColorAnim';
-
- ColorAnim.DEFAULT_BGCOLOR = '#fff';
- // shorthand
- var Y = YAHOO.util;
- YAHOO.extend(ColorAnim, Y.Anim);
-
- var superclass = ColorAnim.superclass;
- var proto = ColorAnim.prototype;
-
- proto.patterns.color = /color$/i;
- proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
- proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
- proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
- proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/; // need rgba for safari
-
- /**
- * Attempts to parse the given string and return a 3-tuple.
- * @method parseColor
- * @param {String} s The string to parse.
- * @return {Array} The 3-tuple of rgb values.
- */
- proto.parseColor = function(s) {
- if (s.length == 3) { return s; }
-
- var c = this.patterns.hex.exec(s);
- if (c && c.length == 4) {
- return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
- }
-
- c = this.patterns.rgb.exec(s);
- if (c && c.length == 4) {
- return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
- }
-
- c = this.patterns.hex3.exec(s);
- if (c && c.length == 4) {
- return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
- }
-
- return null;
- };
-
- proto.getAttribute = function(attr) {
- var el = this.getEl();
- if (this.patterns.color.test(attr) ) {
- var val = YAHOO.util.Dom.getStyle(el, attr);
-
- var that = this;
- if (this.patterns.transparent.test(val)) { // bgcolor default
- var parent = YAHOO.util.Dom.getAncestorBy(el, function(node) {
- return !that.patterns.transparent.test(val);
- });
-
- if (parent) {
- val = Y.Dom.getStyle(parent, attr);
- } else {
- val = ColorAnim.DEFAULT_BGCOLOR;
- }
- }
- } else {
- val = superclass.getAttribute.call(this, attr);
- }
-
- return val;
- };
-
- proto.doMethod = function(attr, start, end) {
- var val;
-
- if ( this.patterns.color.test(attr) ) {
- val = [];
- for (var i = 0, len = start.length; i < len; ++i) {
- val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
- }
-
- val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')';
- }
- else {
- val = superclass.doMethod.call(this, attr, start, end);
- }
-
- return val;
- };
-
- proto.setRuntimeAttribute = function(attr) {
- superclass.setRuntimeAttribute.call(this, attr);
-
- if ( this.patterns.color.test(attr) ) {
- var attributes = this.attributes;
- var start = this.parseColor(this.runtimeAttributes[attr].start);
- var end = this.parseColor(this.runtimeAttributes[attr].end);
- // fix colors if going "by"
- if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) {
- end = this.parseColor(attributes[attr].by);
-
- for (var i = 0, len = start.length; i < len; ++i) {
- end[i] = start[i] + end[i];
- }
- }
-
- this.runtimeAttributes[attr].start = start;
- this.runtimeAttributes[attr].end = end;
- }
- };
-
- Y.ColorAnim = ColorAnim;
-})();
-/*!
-TERMS OF USE - EASING EQUATIONS
-Open source under the BSD License.
-Copyright 2001 Robert Penner All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/**
- * Singleton that determines how an animation proceeds from start to end.
- * @class Easing
- * @namespace YAHOO.util
-*/
-
-YAHOO.util.Easing = {
-
- /**
- * Uniform speed between points.
- * @method easeNone
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @return {Number} The computed value for the current animation frame
- */
- easeNone: function (t, b, c, d) {
- return c*t/d + b;
- },
-
- /**
- * Begins slowly and accelerates towards end.
- * @method easeIn
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @return {Number} The computed value for the current animation frame
- */
- easeIn: function (t, b, c, d) {
- return c*(t/=d)*t + b;
- },
-
- /**
- * Begins quickly and decelerates towards end.
- * @method easeOut
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @return {Number} The computed value for the current animation frame
- */
- easeOut: function (t, b, c, d) {
- return -c *(t/=d)*(t-2) + b;
- },
-
- /**
- * Begins slowly and decelerates towards end.
- * @method easeBoth
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @return {Number} The computed value for the current animation frame
- */
- easeBoth: function (t, b, c, d) {
- if ((t/=d/2) < 1) {
- return c/2*t*t + b;
- }
-
- return -c/2 * ((--t)*(t-2) - 1) + b;
- },
-
- /**
- * Begins slowly and accelerates towards end.
- * @method easeInStrong
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @return {Number} The computed value for the current animation frame
- */
- easeInStrong: function (t, b, c, d) {
- return c*(t/=d)*t*t*t + b;
- },
-
- /**
- * Begins quickly and decelerates towards end.
- * @method easeOutStrong
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @return {Number} The computed value for the current animation frame
- */
- easeOutStrong: function (t, b, c, d) {
- return -c * ((t=t/d-1)*t*t*t - 1) + b;
- },
-
- /**
- * Begins slowly and decelerates towards end.
- * @method easeBothStrong
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @return {Number} The computed value for the current animation frame
- */
- easeBothStrong: function (t, b, c, d) {
- if ((t/=d/2) < 1) {
- return c/2*t*t*t*t + b;
- }
-
- return -c/2 * ((t-=2)*t*t*t - 2) + b;
- },
-
- /**
- * Snap in elastic effect.
- * @method elasticIn
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @param {Number} a Amplitude (optional)
- * @param {Number} p Period (optional)
- * @return {Number} The computed value for the current animation frame
- */
-
- elasticIn: function (t, b, c, d, a, p) {
- if (t == 0) {
- return b;
- }
- if ( (t /= d) == 1 ) {
- return b+c;
- }
- if (!p) {
- p=d*.3;
- }
-
- if (!a || a < Math.abs(c)) {
- a = c;
- var s = p/4;
- }
- else {
- var s = p/(2*Math.PI) * Math.asin (c/a);
- }
-
- return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
- },
-
- /**
- * Snap out elastic effect.
- * @method elasticOut
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @param {Number} a Amplitude (optional)
- * @param {Number} p Period (optional)
- * @return {Number} The computed value for the current animation frame
- */
- elasticOut: function (t, b, c, d, a, p) {
- if (t == 0) {
- return b;
- }
- if ( (t /= d) == 1 ) {
- return b+c;
- }
- if (!p) {
- p=d*.3;
- }
-
- if (!a || a < Math.abs(c)) {
- a = c;
- var s = p / 4;
- }
- else {
- var s = p/(2*Math.PI) * Math.asin (c/a);
- }
-
- return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
- },
-
- /**
- * Snap both elastic effect.
- * @method elasticBoth
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @param {Number} a Amplitude (optional)
- * @param {Number} p Period (optional)
- * @return {Number} The computed value for the current animation frame
- */
- elasticBoth: function (t, b, c, d, a, p) {
- if (t == 0) {
- return b;
- }
-
- if ( (t /= d/2) == 2 ) {
- return b+c;
- }
-
- if (!p) {
- p = d*(.3*1.5);
- }
-
- if ( !a || a < Math.abs(c) ) {
- a = c;
- var s = p/4;
- }
- else {
- var s = p/(2*Math.PI) * Math.asin (c/a);
- }
-
- if (t < 1) {
- return -.5*(a*Math.pow(2,10*(t-=1)) *
- Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
- }
- return a*Math.pow(2,-10*(t-=1)) *
- Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
- },
-
-
- /**
- * Backtracks slightly, then reverses direction and moves to end.
- * @method backIn
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @param {Number} s Overshoot (optional)
- * @return {Number} The computed value for the current animation frame
- */
- backIn: function (t, b, c, d, s) {
- if (typeof s == 'undefined') {
- s = 1.70158;
- }
- return c*(t/=d)*t*((s+1)*t - s) + b;
- },
-
- /**
- * Overshoots end, then reverses and comes back to end.
- * @method backOut
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @param {Number} s Overshoot (optional)
- * @return {Number} The computed value for the current animation frame
- */
- backOut: function (t, b, c, d, s) {
- if (typeof s == 'undefined') {
- s = 1.70158;
- }
- return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
- },
-
- /**
- * Backtracks slightly, then reverses direction, overshoots end,
- * then reverses and comes back to end.
- * @method backBoth
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @param {Number} s Overshoot (optional)
- * @return {Number} The computed value for the current animation frame
- */
- backBoth: function (t, b, c, d, s) {
- if (typeof s == 'undefined') {
- s = 1.70158;
- }
-
- if ((t /= d/2 ) < 1) {
- return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
- }
- return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
- },
-
- /**
- * Bounce off of start.
- * @method bounceIn
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @return {Number} The computed value for the current animation frame
- */
- bounceIn: function (t, b, c, d) {
- return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b;
- },
-
- /**
- * Bounces off end.
- * @method bounceOut
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @return {Number} The computed value for the current animation frame
- */
- bounceOut: function (t, b, c, d) {
- if ((t/=d) < (1/2.75)) {
- return c*(7.5625*t*t) + b;
- } else if (t < (2/2.75)) {
- return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
- } else if (t < (2.5/2.75)) {
- return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
- }
- return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
- },
-
- /**
- * Bounces off start and end.
- * @method bounceBoth
- * @param {Number} t Time value used to compute current value
- * @param {Number} b Starting value
- * @param {Number} c Delta between start and end values
- * @param {Number} d Total length of animation
- * @return {Number} The computed value for the current animation frame
- */
- bounceBoth: function (t, b, c, d) {
- if (t < d/2) {
- return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b;
- }
- return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
- }
-};
-
-(function() {
-/**
- * Anim subclass for moving elements along a path defined by the "points"
- * member of "attributes". All "points" are arrays with x, y coordinates.
- * <p>Usage: <code>var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
- * @class Motion
- * @namespace YAHOO.util
- * @requires YAHOO.util.Anim
- * @requires YAHOO.util.AnimMgr
- * @requires YAHOO.util.Easing
- * @requires YAHOO.util.Bezier
- * @requires YAHOO.util.Dom
- * @requires YAHOO.util.Event
- * @requires YAHOO.util.CustomEvent
- * @constructor
- * @extends YAHOO.util.ColorAnim
- * @param {String | HTMLElement} el Reference to the element that will be animated
- * @param {Object} attributes The attribute(s) to be animated.
- * Each attribute is an object with at minimum a "to" or "by" member defined.
- * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
- * All attribute names use camelCase.
- * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
- * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
- */
- var Motion = function(el, attributes, duration, method) {
- if (el) { // dont break existing subclasses not using YAHOO.extend
- Motion.superclass.constructor.call(this, el, attributes, duration, method);
- }
- };
-
-
- Motion.NAME = 'Motion';
-
- // shorthand
- var Y = YAHOO.util;
- YAHOO.extend(Motion, Y.ColorAnim);
-
- var superclass = Motion.superclass;
- var proto = Motion.prototype;
-
- proto.patterns.points = /^points$/i;
-
- proto.setAttribute = function(attr, val, unit) {
- if ( this.patterns.points.test(attr) ) {
- unit = unit || 'px';
- superclass.setAttribute.call(this, 'left', val[0], unit);
- superclass.setAttribute.call(this, 'top', val[1], unit);
- } else {
- superclass.setAttribute.call(this, attr, val, unit);
- }
- };
-
- proto.getAttribute = function(attr) {
- if ( this.patterns.points.test(attr) ) {
- var val = [
- superclass.getAttribute.call(this, 'left'),
- superclass.getAttribute.call(this, 'top')
- ];
- } else {
- val = superclass.getAttribute.call(this, attr);
- }
-
- return val;
- };
-
- proto.doMethod = function(attr, start, end) {
- var val = null;
-
- if ( this.patterns.points.test(attr) ) {
- var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
- val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
- } else {
- val = superclass.doMethod.call(this, attr, start, end);
- }
- return val;
- };
-
- proto.setRuntimeAttribute = function(attr) {
- if ( this.patterns.points.test(attr) ) {
- var el = this.getEl();
- var attributes = this.attributes;
- var start;
- var control = attributes['points']['control'] || [];
- var end;
- var i, len;
-
- if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points
- control = [control];
- } else { // break reference to attributes.points.control
- var tmp = [];
- for (i = 0, len = control.length; i< len; ++i) {
- tmp[i] = control[i];
- }
- control = tmp;
- }
-
- if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative
- Y.Dom.setStyle(el, 'position', 'relative');
- }
-
- if ( isset(attributes['points']['from']) ) {
- Y.Dom.setXY(el, attributes['points']['from']); // set position to from point
- }
- else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position
-
- start = this.getAttribute('points'); // get actual top & left
-
- // TO beats BY, per SMIL 2.1 spec
- if ( isset(attributes['points']['to']) ) {
- end = translateValues.call(this, attributes['points']['to'], start);
-
- var pageXY = Y.Dom.getXY(this.getEl());
- for (i = 0, len = control.length; i < len; ++i) {
- control[i] = translateValues.call(this, control[i], start);
- }
-
-
- } else if ( isset(attributes['points']['by']) ) {
- end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
-
- for (i = 0, len = control.length; i < len; ++i) {
- control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
- }
- }
-
- this.runtimeAttributes[attr] = [start];
-
- if (control.length > 0) {
- this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
- }
-
- this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
- }
- else {
- superclass.setRuntimeAttribute.call(this, attr);
- }
- };
-
- var translateValues = function(val, start) {
- var pageXY = Y.Dom.getXY(this.getEl());
- val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
-
- return val;
- };
-
- var isset = function(prop) {
- return (typeof prop !== 'undefined');
- };
-
- Y.Motion = Motion;
-})();
-(function() {
-/**
- * Anim subclass for scrolling elements to a position defined by the "scroll"
- * member of "attributes". All "scroll" members are arrays with x, y scroll positions.
- * <p>Usage: <code>var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
- * @class Scroll
- * @namespace YAHOO.util
- * @requires YAHOO.util.Anim
- * @requires YAHOO.util.AnimMgr
- * @requires YAHOO.util.Easing
- * @requires YAHOO.util.Bezier
- * @requires YAHOO.util.Dom
- * @requires YAHOO.util.Event
- * @requires YAHOO.util.CustomEvent
- * @extends YAHOO.util.ColorAnim
- * @constructor
- * @param {String or HTMLElement} el Reference to the element that will be animated