From: Simon H. <sim...@us...> - 2010-09-30 16:56:53
|
Update of /cvsroot/stack/stack-dev/lib/database In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv28438/lib/database Modified Files: devCache.php StackDBItem.php StackDBAttemptPRTMeta.php StackDBBackup.php StackDBUser.php StackDB.php StackDBADOdb.php MoodleDB.php StackDBMySQL.php StackDBReporting.php StackDBCache.php Log Message: Merging 2.2 branch (with some additional fixes to ensure seamless updating for version lines) Index: MoodleDB.php =================================================================== RCS file: /cvsroot/stack/stack-dev/lib/database/MoodleDB.php,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** MoodleDB.php 27 Aug 2009 16:23:00 -0000 1.14 --- MoodleDB.php 30 Sep 2010 16:56:13 -0000 1.15 *************** *** 70,78 **** public function batchAdd($questions, $userID, $engineID, $category='1') { if(!empty($questions)) { foreach($questions as $question) { ! $result = $this->addQuestion($question, $userID, $engineID, $category); if($result == false) --- 70,79 ---- public function batchAdd($questions, $userID, $engineID, $category='1') { + $this->logger->debug("busy: $questions, $userID, $engineID, $category"); if(!empty($questions)) { foreach($questions as $question) { ! $result = $this->addQuestion($question, NULL, $userID, $engineID, $category); // line is unchanged if($result == false) *************** *** 106,118 **** * @return bool $return true if successful */ ! public function addQuestion($stackID, $userID, $engineID, $category='1') { global $config; $moodleEnabled = $config->getMoodle('enabled'); if(($moodleEnabled == 'true') && ($engineID != NULL)) //if moodle config is setup { //load up the question from the stack db & grab its name, grade & guid. ! $item = new Item(NULL, $stackID); $itemName = $item->questionName->getSelection(); --- 107,120 ---- * @return bool $return true if successful */ ! public function addQuestion($id, $line, $userID, $engineID, $category='1') { global $config; $moodleEnabled = $config->getMoodle('enabled'); + $this->logger->debug("mycat:".$category." and userid:".$userID); if(($moodleEnabled == 'true') && ($engineID != NULL)) //if moodle config is setup { //load up the question from the stack db & grab its name, grade & guid. ! $item = new Item(NULL, $id); $itemName = $item->questionName->getSelection(); *************** *** 134,144 **** //check whether the question is already in the moodle question bank. ! $inQBank = $this->inMoodleQuestionBank($stackID, $engineID); if($inQBank === false) { //add the question ! return $this->newQuestion($engineID, $userID, $category, $itemID, $itemName, $itemMaxMark, $itemGUID); } else { //update the question(s) return $this->updateQuestion($inQBank, $engineID, $userID, $category, $itemID, $itemName, $itemMaxMark, $itemGUID); } --- 136,149 ---- //check whether the question is already in the moodle question bank. ! $inQBank = $this->inMoodleQuestionBank($id, $engineID); ! $this->logger->debug("tap"); if($inQBank === false) { + $this->logger->debug("noob q"); //add the question ! return $this->newQuestion($engineID, $userID, $category, $itemID, $line, $itemName, $itemMaxMark, $itemGUID); } else { //update the question(s) + $this->logger->debug("updating q in $inQBank"); return $this->updateQuestion($inQBank, $engineID, $userID, $category, $itemID, $itemName, $itemMaxMark, $itemGUID); } *************** *** 163,167 **** protected function updateQuestion($qID, $engineID, $userID, $category, $stackID, $qName, $qMaxMark, $qGUID) { ! $this->logger->finer("Updating item $stackID to Moodles database"); global $config; $prefix = $config->getMoodle('prefix'); --- 168,173 ---- protected function updateQuestion($qID, $engineID, $userID, $category, $stackID, $qName, $qMaxMark, $qGUID) { ! $this->logger->debug("Updating item $stackID to Moodles database"); ! global $config; $prefix = $config->getMoodle('prefix'); *************** *** 188,191 **** --- 194,209 ---- $result = false; } + + $sql = "UPDATE {$prefix}question_opaque SET + remoteid = ".$this->dbSafeString('q'.$stackID).", + WHERE questionid = $id"; + + $result = $this->query($sql); + if(!$result){ + $this->logger->error("Failed to add the question to the opaque_questions table"); + } + else{ + $this->logger->finer("Added to opaque_questions table"); + } } return true; *************** *** 203,210 **** * @return bool */ ! protected function newQuestion($engineID, $userID, $category, $stackID, $qName, $qMaxMark, $qGUID) { ! $this->logger->finer("Adding item $stackID to Moodles database"); ! $stackID = 'q'.$stackID; global $config; $prefix = $config->getMoodle('prefix'); --- 221,232 ---- * @return bool */ ! protected function newQuestion($engineID, $userID, $category, $versionID, $lineID, $qName, $qMaxMark, $qGUID) { ! if($lineID == NULL) $lineID = 12345; ! ! $this->logger->debug("Adding item $versionID (line $lineID) to Moodles database by user: $userID"); ! ! ! global $config; $prefix = $config->getMoodle('prefix'); *************** *** 235,239 **** $category, 0, ".$this->dbSafeString($qName)." , ".$this->dbSafeString('').", 0, ".$this->dbSafeString('').", ".$this->dbSafeString('').", $qMaxMark, 0,".$this->dbSafeString(QTYPE).", 1, ".$this->dbSafeString($qGUID).", ".$this->dbSafeString($timestamp).", 0, $timestamp, $timestamp, $userID );"; ! $this->connectMoodleDB(); $added = $this->query($sql); --- 257,261 ---- $category, 0, ".$this->dbSafeString($qName)." , ".$this->dbSafeString('').", 0, ".$this->dbSafeString('').", ".$this->dbSafeString('').", $qMaxMark, 0,".$this->dbSafeString(QTYPE).", 1, ".$this->dbSafeString($qGUID).", ".$this->dbSafeString($timestamp).", 0, $timestamp, $timestamp, $userID );"; ! $this->logger->finer("trying adding to moodle question bank with sql: $sql"); $this->connectMoodleDB(); $added = $this->query($sql); *************** *** 253,257 **** remoteversion ) ! VALUES ( $qid, $engineID, ".$this->dbSafeString($stackID).", ".$this->dbSafeString('1.0').");"; $result = $this->query($sql); --- 275,279 ---- remoteversion ) ! VALUES ( $qid, $engineID, ".$this->dbSafeString('q'.$versionID).", ".$this->dbSafeString($lineID.'.'.$versionID).");"; // some redundancy for now until versioning get more sophisticated, e.g. with milestones $result = $this->query($sql); *************** *** 594,597 **** --- 616,706 ---- } } + + /** + * PROBABLY NOT NEEDED + * Return an mapping from the quizzes the student has taken to the attempts made. + * @access public + * @param int $student + * @return array $attempts + */ + public function getQuizAttempts($student, $course = NULL) { + global $config; + $prefix = $config->getMoodle('prefix'); + if(NULL == $course) { // irrespective of course + $sql = "SELECT quiz, {$prefix}quiz_attempts.id FROM {$prefix}quiz_attempts WHERE userid = ".$this->dbSafeString($student); + } else { // course specific + $sql = "SELECT quiz, {$prefix}quiz_attempts.id FROM {$prefix}quiz_attempts, {$prefix}quiz " . + "WHERE userid = ".$this->dbSafeString($student). + " AND course =".$this->dbSafeString($course). + " AND {$prefix}quiz.id = quiz"; + } + //$this->logger->debug($sql); + $result = $this->query($sql); + $attempts = NULL; + if($result) { + for($i = 0; $i < $this->noRows(); $i++) { + $attempts[$this->result($i, 'quiz')][] = $this->result($i, 'id'); // NOT result($i, 'attempt')! + } + } + return $attempts; + } + + /** + * Return an mapping from the questions the student has attempted to the attempt. + * @access public + * @param int $student + * @return array $attempts + */ + public function getQuestionAttempts($student, $course = NULL) { + global $config; + $prefix = $config->getMoodle('prefix'); + if(NULL == $course) { // irrespective of course + $sql = "SELECT quiz, {$prefix}quiz_attempts.id FROM {$prefix}quiz_attempts WHERE userid = ".$this->dbSafeString($student); + } else { // course specific + $sql = "SELECT quiz, {$prefix}quiz_attempts.id FROM {$prefix}quiz_attempts, {$prefix}quiz " . + "WHERE userid = ".$this->dbSafeString($student). + " AND course =".$this->dbSafeString($course). + " AND {$prefix}quiz.id = quiz"; + } + //$this->logger->debug($sql); + $result = $this->query($sql); + $attempts = NULL; + if($result) { + for($i = 0; $i < $this->noRows(); $i++) { + $attempts[$this->result($i, 'quiz')][] = $this->result($i, 'id'); // NOT result($i, 'attempt')! + } + } + return $attempts; + } + + /** + * Return all the responses from the student for the given attempt, in order, as well as (Moodle) question id + * @access public + * @param int $attempt + * @return array $responses + */ + public function getQuestionAttemptResponses($attempt) { + global $config; + $prefix = $config->getMoodle('prefix'); + + $sql = "SELECT seq_number, answer, event, question, remoteid" . + " FROM {$prefix}question_states, {$prefix}question_opaque" . + " WHERE attempt = ".$this->dbSafeString($attempt). + " AND {$prefix}question_opaque.questionid = {$prefix}question_states.question". + " ORDER BY seq_number"; + + $result = $this->query($sql); + // $responses = NULL; + if($result) { + for($i = 0; $i < $this->noRows(); $i++) { + $q = $this->result($i, 'question'); + $s = $this->result($i, 'seq_number'); + $return[$q]['version'] = substr($this->result($i, 'remoteid'), 1); // strip off 'q' + $return[$q][$s]['answer'] = $this->result($i, 'answer'); + $return[$q][$s]['event'] = $this->result($i, 'event'); + } + } + return $return; + } } Index: StackDBAttemptPRTMeta.php =================================================================== RCS file: /cvsroot/stack/stack-dev/lib/database/StackDBAttemptPRTMeta.php,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** StackDBAttemptPRTMeta.php 29 Jan 2010 11:03:08 -0000 1.8 --- StackDBAttemptPRTMeta.php 30 Sep 2010 16:56:13 -0000 1.9 *************** *** 114,120 **** } } - - - } --- 114,117 ---- Index: StackDB.php =================================================================== RCS file: /cvsroot/stack/stack-dev/lib/database/StackDB.php,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** StackDB.php 27 Aug 2009 16:23:00 -0000 1.5 --- StackDB.php 30 Sep 2010 16:56:13 -0000 1.6 *************** *** 78,81 **** --- 78,83 ---- public function allResults($field = NULL); + + //public function last_insert_id(); } Index: StackDBADOdb.php =================================================================== RCS file: /cvsroot/stack/stack-dev/lib/database/StackDBADOdb.php,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** StackDBADOdb.php 27 May 2010 11:10:09 -0000 1.9 --- StackDBADOdb.php 30 Sep 2010 16:56:13 -0000 1.10 *************** *** 349,354 **** } ! public function insert_id() { ! return Insert_ID(); // PO_Insert_ID() is a more portable but untested alternative. } --- 349,354 ---- } ! public function last_insert_id() { ! return $this->conn->Insert_ID(); // PO_Insert_ID() is a more portable but untested alternative. } Index: StackDBUser.php =================================================================== RCS file: /cvsroot/stack/stack-dev/lib/database/StackDBUser.php,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** StackDBUser.php 27 Aug 2009 16:23:00 -0000 1.7 --- StackDBUser.php 30 Sep 2010 16:56:13 -0000 1.8 *************** *** 157,160 **** --- 157,179 ---- /** + * Returns a count of moodle users + * @param int $userid + * @return int $number + */ + public function countUsers() + { + global $config; + $prefix = $config->getMoodle('prefix'); + $sql = 'SELECT COUNT(id) as count + FROM '.$prefix.'user'; + + $this->connect(); + $this->query($sql); + $this->disconnect(); + + return $this->result(0, 'count'); + } + + /** * Returns a list of a user's moodle capabilities. (NOTE: Does not take context into account). * *************** *** 231,235 **** } } - } --- 250,253 ---- Index: StackDBCache.php =================================================================== RCS file: /cvsroot/stack/stack-dev/lib/database/StackDBCache.php,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** StackDBCache.php 27 May 2010 15:34:14 -0000 1.21 --- StackDBCache.php 30 Sep 2010 16:56:13 -0000 1.22 *************** *** 50,57 **** // add a transition using the new state id ! $transition = $this->addTransition($lastNode, $stateID, $post, $event); ! // add attempt_meta information ! if($userEvent) $this->addMeta($stateID, $state); } --- 50,59 ---- // add a transition using the new state id ! if($stateID !== NULL) { // state added successfully: go ahead and reference it! ! $transition = $this->addTransition($lastNode, $stateID, $post, $event); ! // add attempt_meta information ! if($userEvent) $this->addMeta($stateID, $state); ! } } *************** *** 59,63 **** $this->query("UNLOCK TABLES"); ! return $transition; // either the new or recent prior one } --- 61,65 ---- $this->query("UNLOCK TABLES"); ! return $transition; // either the new or recent prior one (or NULL on failure) } *************** *** 78,88 **** ", NOW())"; ! $this->query($sql); ! // NOTE: if this fails it will mess the transition table because of 'last index' method below. ! $this->logger->debug("SQL debug: ".$sql); ! // would be nice to be able to obtain the index for the last insert (like mysql_insert_id) without this extra call but would require extending the StackDB interface ! $this->query("SELECT id FROM display_cache ORDER BY id DESC LIMIT 1"); // safe for multi-threading? if($this->noRows()<=0) { // no rows in display_cache? --- 80,92 ---- ", NOW())"; ! //$this->logger->debug("SQL:".$sql); ! $result = $this->query($sql); ! if(empty($result)) { // insert failed! ! $this->logger->critical("Failed to store a question state!"); ! return NULL; // don't add a transition! ! } // would be nice to be able to obtain the index for the last insert (like mysql_insert_id) without this extra call but would require extending the StackDB interface ! $this->query("SELECT id FROM display_cache ORDER BY id DESC LIMIT 1"); // safe for multi-threading if higher-level lock maintained if($this->noRows()<=0) { // no rows in display_cache? *************** *** 227,231 **** */ public function nextNode($transition) { - // takes current node and posted answers // returns next node id (used for obtaining cache state) $sql = "SELECT nextNode FROM display_cache_sequence " . --- 231,234 ---- *************** *** 327,330 **** --- 330,353 ---- } + /* + * Determines whether a question can be changed without fear. + * i.e. even if it has available initial states, these have not been processed. + */ + public function hasActiveStates($qID) { + // initial states have a transition from a state id of 0 + + // get all starting configs for given question + $sql = "SELECT display_cache.id, display_cache.state FROM display_cache_sequence, display_cache " . + "LEFT JOIN display_cache_sequence AS successor " . + "ON successor.currentNode = $qID ". + "WHERE display_cache.qID = $qID " . + "AND display_cache_sequence.currentNode = 0 " . + "AND display_cache_sequence.nextNode = display_cache.id"; + $this->query($sql); + + // return 0 if question not deployed + return ($this->noRows() === 0); + } + /** * Empties the entire cache *************** *** 384,388 **** $this->query($sql); - //echo "<pre>";print_r($this); echo"</pre>"; $xhtml = '<table id="transitionstable" border=1>'; --- 407,410 ---- *************** *** 446,450 **** public function showInitialStates($qid) { - //$sql .= "SELECT * FROM display_cache WHERE qID=".$qid." ORDER BY id"; $sql = "SELECT display_cache.* FROM display_cache_sequence, display_cache " . "WHERE display_cache.qID = $qid " . --- 468,471 ---- *************** *** 453,461 **** $this->query($sql); //echo "<pre>";print_r($this); echo"</pre>"; ! $xhtml = "<h2>Initial states for question #$qid</h2>"; $xhtml .= '<table id="statestable" border=1>'; ! $xhtml .= '<tr><th>id</th><th>answers</th><th>current / total mark</th><th>exp.</th><th>questionNote</th><th>xhtml</th></tr>'; for ($i=0; $i<$this->noRows(); $i++) { $post = $this->base64_unserialize($this->result($i, 'post')); --- 474,538 ---- $this->query($sql); + //echo $this->noRows(); + + // store these initial states since we'll need to use the connection for finding successive states + for ($i=0; $i<$this->noRows(); $i++) { + $id = $this->result($i,'id'); + $initials[$id]['id'] = $id; + $initials[$id]['post'] = $this->base64_unserialize($this->result($i, 'post')); + $initials[$id]['state'] = $this->base64_unserialize($this->result($i, 'state')); + $initials[$id]['answers'] = $this->pretty_post($this->base64_unserialize($this->result($i, 'answers')), true); + $initials[$id]['currentTotalMark'] = $this->result($i, 'currentTotalMark'); + $initials[$id]['totalPossibleMarks'] = $this->result($i, 'totalPossibleMarks'); + $initials[$id]['expired'] = $this->result($i, 'expired'); + $initials[$id]['questionNote'] = $this->result($i, 'questionNote'); + $initials[$id]['xhtml'] = $this->result($i,'xhtml'); + } //echo "<pre>";print_r($this); echo"</pre>"; ! $xhtml .= '<table id="statestable" border=1>'; ! $xhtml .= '<tr><th>id</th><th>answers</th><th>current / total mark</th><th>exp.</th><th>questionNote</th><th>xhtml</th><th>transitions</th></tr>'; ! ! foreach($initials as $i) { ! $xhtml .= '<td>'.$i['id'].'</td>'; ! $xhtml .= '<td>'.$i['answers'].'</td>'; ! $xhtml .= '<td>'.$i['currentTotalMark'].' / '.$i['totalPossibleMarks'].'</td>'; ! $xhtml .= '<td>'.$i['expired'].'</td>'; ! $xhtml .= '<td>'.$i['questionNote'].'</td>'; ! $xhtml .= '<td>'.$i['xhtml'].'</td>'; ! ! $xhtml .= '<td>'.$this->innerTransitionsTable($i['id']).'</td></tr>'; ! } ! $xhtml .= '</table>'; ! return $xhtml; ! } ! ! private function innerTransitionsTable($id) { ! $transitions = $this->stateTransitions($id); ! $xhtml = ''; ! if($transitions) { ! $xhtml .= '<table>'; // start inner table ! foreach($transitions as $t) { ! if($t['previous'] !== null) { ! if($t['previous'] > 0) $xhtml .= '<tr><td><a href="?sid='.$t['previous'].'">« back to '.$t[previous].'</a></td></tr>'; ! } ! else if($t['nextNode'] != $id) $xhtml .= ! '<tr><td><a href="?sid='.$t['nextNode'].'">» '.$this->pretty_post($this->base64_unserialize($t['post'])).'</a> ('.$t['event'].')</td></tr>'; ! else $xhtml .= '(loopback) '.$this->pretty_post($this->base64_unserialize($t['post'])); ! } ! $xhtml .= '</table>'; // end inner table ! } ! return $xhtml; ! } ! ! public function showCacheState($id) { ! $sql .= "SELECT * FROM display_cache WHERE id=".$id; ! ! $this->query($sql); ! ! //echo "<pre>";print_r($this); echo"</pre>"; ! $xhtml .= '<table id="statestable" border=1>'; ! $xhtml .= '<tr><th>id</th><th>answers</th><th>current / total mark</th><th>exp.</th><th>questionNote</th><th>xhtml</th><th>transitions</th></tr>'; for ($i=0; $i<$this->noRows(); $i++) { $post = $this->base64_unserialize($this->result($i, 'post')); *************** *** 468,503 **** $xhtml .= '<td>'. $this->result($i, 'questionNote') .'</td>'; $xhtml .= '<td>'. $this->result($i,'xhtml').'</td>'; ! $xhtml .= '</tr>'; } - - $xhtml .= '</table>'; return $xhtml; } ! public function showCacheState($id) { ! $sql .= "SELECT * FROM display_cache WHERE id=".$id; ! ! //$this->query($sql); $this->query($sql); ! //echo "<pre>";print_r($this); echo"</pre>"; ! $xhtml = '<table id="statestable" border=1>'; ! $xhtml .= '<tr><th>id</th><th>qID</th><th>answers</th><th>current total mark</th><th>total possible marks</th><th>exp.</th><th>questionNote</th><th>xhtml</th></tr>'; ! ! $post = $this->base64_unserialize($this->result(0, 'post')); ! $state = $this->base64_unserialize($this->result(0, 'state')); ! $xhtml .= '<tr><td>'. $this->result(0,'id').'</td>'; ! $xhtml .= '<td>'. $this->result(0,'qID') .'</td>'; ! //$xhtml .= '<td>'.$this->elementsToHTML($state).'</td>'; ! $xhtml .= '<td>'. $this->pretty_post($this->base64_unserialize($this->result($i, 'answers')), true) .'</td>'; ! $xhtml .= '<td>'. $this->result(0, 'currentTotalMark') .'</td>'; ! $xhtml .= '<td>'. $this->result(0, 'totalPossibleMarks') .'</td>'; ! $xhtml .= '<td>'. $this->result(0, 'expired') .'</td>'; ! $xhtml .= '<td>'. $this->result(0, 'questionNote') .'</td>'; ! $xhtml .= '<td>'. $this->result(0,'xhtml').'</td>'; ! $xhtml .= '</tr>'; ! ! $xhtml .= '</table>'; ! return $xhtml; } --- 545,572 ---- $xhtml .= '<td>'. $this->result($i, 'questionNote') .'</td>'; $xhtml .= '<td>'. $this->result($i,'xhtml').'</td>'; ! $xhtml .= '<td>'; ! $xhtml .= $this->innerTransitionsTable($this->result($i,'id')); ! $xhtml .= '</td></tr>'; } return $xhtml; } ! private function stateTransitions($id) ! { ! $sql = "SELECT * FROM display_cache_sequence WHERE currentNode=$id OR nextNode=$id"; $this->query($sql); + for ($i=0; $i<$this->noRows(); $i++) { + $tid = $this->result($i,'id'); + if($this->result($i, 'currentNode') == $id) { // transition FROM this node + $transitions[$tid]['nextNode'] = $this->result($i, 'nextNode'); + $transitions[$tid]['post'] = $this->result($i, 'post'); + $transitions[$tid]['event'] = $this->result($i, 'event'); + } else { // transition TO this node + $transitions[$tid]['previous'] = $this->result($i, 'currentNode'); + } + } ! //print_r($transitions); ! return $transitions; } *************** *** 542,546 **** } // potentially costly item deserialisation but can we justify an extra field for reversion? ! $item = $this->base64_unserialize($this->result($i, 'state')); //$array['version'] = $item->getVersion(); --- 611,615 ---- } // potentially costly item deserialisation but can we justify an extra field for reversion? ! //$item = $this->base64_unserialize($this->result($i, 'state')); //$array['version'] = $item->getVersion(); *************** *** 616,620 **** /** ! * Effectively 'undeploys' a question instance without removing it (and it's sucessors) from * the cache as dropState() does. */ --- 685,689 ---- /** ! * Effectively 'undeploys' a version instance without removing it (and it's sucessors) from * the cache as dropState() does. */ *************** *** 622,625 **** --- 691,702 ---- $this->query("DELETE FROM display_cache_sequence WHERE currentNode=0 AND nextNode=$id"); } + + // checks whether a version is deployed, i.e. has instances which are initial states + // return number of insances deployed + public function instancesDeployed($id) { + $this->query("SELECT * FROM display_cache, display_cache_sequence " . + "WHERE display_cache.qID=$id AND currentNode=0 AND nextNode=display_cache.id"); + return $this->noRows(); + } } ?> \ No newline at end of file Index: devCache.php =================================================================== RCS file: /cvsroot/stack/stack-dev/lib/database/devCache.php,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** devCache.php 24 May 2010 16:44:42 -0000 1.13 --- devCache.php 30 Sep 2010 16:56:13 -0000 1.14 *************** *** 26,32 **** $cache->connect(); ! $qidfilter = $_GET['qid']; ! $startrow = isset($_GET['startrow']) ? $_GET['startrow'] : 0; ! $rowcount = isset($_GET['rowcount']) ? $_GET['rowcount'] : 10; // process button presses --- 26,30 ---- $cache->connect(); ! $qid = $_GET['qid']; // process button presses *************** *** 42,46 **** ?> <head> ! <title>Direct Cache Access</title> <style> .box { --- 40,44 ---- ?> <head> ! <title>CAS Cache Admin</title> <style> .box { *************** *** 61,107 **** } </style> </head> ! <div class="box"> ! <?php if(isset($qidfilter)) ! echo $qidfilter == '*' ? $cache->dumpCacheSequence() : $cache->dumpCacheSequence($qidfilter); ! ?> ! </div> ! <div class="box"> <?php ! $allQs = $cache->getQuestionIDs(); if(NULL !== $allQs) { ! echo "Show question: "; ! if($quidfilter !== '*') echo "<a href='devCache.php?qid=*'>All</a> "; ! else echo "All "; ! foreach($allQs as $qid) { ! if($qid == $qidfilter) echo $qid." "; ! else echo "<a href='?qid=".$qid."'>$qid</a> "; } } else echo "Cache is completely empty."; - ?> - <form method="POST" action="devCache.php"> - <input type="submit" value="Refresh"> - <input type="submit" name="op" value="clear successive states"> - <input type="submit" name="op" onClick="return confirm('Are you sure you want to clear the ENTIRE cache?')" value="clear ENTIRE cache"> - </form> - </div> - <br clear="left" /> - <?php /*$cache->cacheStatePager();*/ ?> - <br clear="left" /> <?php ! if(isset($qidfilter)) ! echo $qidfilter == '*' ? $cache->dumpCacheState(null, $rowcount, $startrow) : $cache->dumpCacheState($qidfilter, $rowcount, $startrow); ?> <script> $(document).ready(function() { ! $('table#statestable td:last-child') .wrapInner('<div class="hidden">') .mouseover(function(x) {$(this).children('.hidden').slideDown('fast').next().remove()}) ! .append('<p>hover over to view</p>'); $('tr:odd').css('background-color', '#e6e6e6'); }); ! </script> \ No newline at end of file --- 59,113 ---- } + .freq { + color: #ccc; + font-size: small; + } + </style> </head> ! <body> ! <form method="POST" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>"> ! <input type="submit" name="op" value="clear non-initial states"> ! <input type="submit" name="op" onClick="return confirm('Are you sure you want to clear the ENTIRE cache?')" value="clear ENTIRE cache"> ! <b>Note:</b> Initial states represent deployed questions. ! </form> ! ! ! <h2>Questions with cached states</h2> <?php ! $allQs = $cache->getQuestionFreqs(); if(NULL !== $allQs) { ! echo "Questions: "; ! foreach($allQs as $id => $freq) { ! if($id == $qid) echo $id."<span class='freq'>×$freq</span> "; ! else echo "<a href='?qid=".$id."'>$id</a><span class='freq'>×$freq</span> "; } } else echo "Cache is completely empty."; ?> <?php ! //var_dump($qid); ! if(isset($_GET['sid'])) { ! echo "<h2>State #$_GET[sid]</h2>"; ! echo $cache->showCacheState($_GET['sid']); ! } ! ! if(!empty($qid)) { ! echo "<h2>Initial states for question #$qid</h2>"; ! echo $cache->showInitialStates($qid); ! } ! ! //echo $cache->dumpCacheSequence($qid); ?> <script> $(document).ready(function() { ! /* $('table#statestable td:last-child') .wrapInner('<div class="hidden">') .mouseover(function(x) {$(this).children('.hidden').slideDown('fast').next().remove()}) ! .append('<p>hover over to view</p>');*/ $('tr:odd').css('background-color', '#e6e6e6'); + $('tr:even').css('background-color', '#ffffff'); }); ! </script> ! </body> \ No newline at end of file Index: StackDBReporting.php =================================================================== RCS file: /cvsroot/stack/stack-dev/lib/database/StackDBReporting.php,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -d -r1.27 -r1.28 *** StackDBReporting.php 16 Sep 2009 12:04:22 -0000 1.27 --- StackDBReporting.php 30 Sep 2010 16:56:13 -0000 1.28 *************** *** 26,30 **** * Provides the database functions for reporting students answers. * - * */ class StackDBReporting extends StackDBADOdb { --- 26,29 ---- *************** *** 43,593 **** } [...1354 lines suppressed...] + // { + // $attemptId = $this->result($i, 'AttemptID'); + // $questionId = $this->result($i, 'QuestionID'); + // $userId = $this->result($i, 'UserID'); + // $PRTName = $this->result($i, 'PRTName'); + // $RawMark = $this->result($i, 'RawMark'); + // $ModMark = $this->result($i, 'ModMark'); + // + // if(!array_key_exists($questionId, $resultsArray) || !array_key_exists($userId, $resultsArray[$questionId])) + // { + // $resultsArray[$questionId][$userId] = new MarksAttempt($userId, $questionId); + // } + // $resultsArray[$questionId][$userId]->addAttempt($attemptId, $PRTName, $RawMark, $ModMark); + // } + // + // return $resultsArray; + // } + // } Index: StackDBBackup.php =================================================================== RCS file: /cvsroot/stack/stack-dev/lib/database/StackDBBackup.php,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** StackDBBackup.php 27 Aug 2009 16:23:00 -0000 1.5 --- StackDBBackup.php 30 Sep 2010 16:56:13 -0000 1.6 *************** *** 19,25 **** * Database backup functions */ ! require_once 'StackDBMySQL.php'; ! class StackDBBackup extends StackDBMySQL { // Attributes --- 19,25 ---- * Database backup functions */ ! require_once 'StackDBADOdb.php'; ! class StackDBBackup extends StackDBADOdb { // Attributes Index: StackDBItem.php =================================================================== RCS file: /cvsroot/stack/stack-dev/lib/database/StackDBItem.php,v retrieving revision 1.35 retrieving revision 1.36 diff -C2 -d -r1.35 -r1.36 *** StackDBItem.php 5 Feb 2010 15:52:07 -0000 1.35 --- StackDBItem.php 30 Sep 2010 16:56:13 -0000 1.36 *************** *** 71,74 **** --- 71,75 ---- questionKeywords , questionUserLastEdited , + line , questionPublisher , questionFormat , *************** *** 90,96 **** ) VALUES ( ! $meta[questionGUID], $meta[questionName], $meta[questionDescription], $meta[questionKeywords], $meta[lastUserEditor], $meta[questionPublisher], $meta[questionFormat], $meta[language], $meta[questionRights], $meta[questionLearningContext], $meta[questionDifficulty], $meta[questionCompetency], $meta[questionCompentencyLevel], $meta[questionTimeAllocated], $meta[questionExerciseType], ".$this->conn->sysTimeStamp." , ".$this->dbSafeString($dbQuestionVariables).", ".$this->dbSafeString($dbItemOptions).", ".$this->dbSafeString($dbItemTests)." , ".$this->dbSafeString($valid==1?1:0)." , ".$this->dbSafeString($status)." , ".$this->dbSafeString($published).");"; ! $added = $this->query($sql); if($added) --- 91,97 ---- ) VALUES ( ! $meta[questionGUID], $meta[questionName], $meta[questionDescription], $meta[questionKeywords], $meta[lastUserEditor], $meta[line], $meta[questionPublisher], $meta[questionFormat], $meta[language], $meta[questionRights], $meta[questionLearningContext], $meta[questionDifficulty], $meta[questionCompetency], $meta[questionCompentencyLevel], $meta[questionTimeAllocated], $meta[questionExerciseType], ".$this->conn->sysTimeStamp." , ".$this->dbSafeString($dbQuestionVariables).", ".$this->dbSafeString($dbItemOptions).", ".$this->dbSafeString($dbItemTests)." , ".$this->dbSafeString($valid==1?1:0)." , ".$this->dbSafeString($status)." , ".$this->dbSafeString($published).");"; + $this->logger->debug($sql); $added = $this->query($sql); if($added) *************** *** 98,103 **** //get question id for newly added item & return. //$result = $this->query("SELECT `questionID` FROM `stackQuestion` WHERE `questionGUID` = '$meta[questionGUID]'"); ! $result = $this->query("SELECT max(questionId) FROM stackquestion"); ! $result = $this->result(0,0); //echo 'Last inserted: '.$result; } --- 99,104 ---- //get question id for newly added item & return. //$result = $this->query("SELECT `questionID` FROM `stackQuestion` WHERE `questionGUID` = '$meta[questionGUID]'"); ! $result = $this->query("SELECT questionID FROM stackquestion ORDER BY questionID desc limit 1"); ! $result = $this->result(0,'questionID'); //echo 'Last inserted: '.$result; } *************** *** 117,123 **** * @return int * @access public ! */ public function updateItem($id, $dbItemOptions, $dbItemTests, $dbQuestionVariables, $meta, $valid, $status, $published) { //make meta db safe foreach($meta as $label => $val) --- 118,128 ---- * @return int * @access public ! * public function updateItem($id, $dbItemOptions, $dbItemTests, $dbQuestionVariables, $meta, $valid, $status, $published) { + return addNewItem($dbItemOptions, $dbItemTests, $dbQuestionVariables, $meta, $valid, $status, $published); + + //update line + /* //make meta db safe foreach($meta as $label => $val) *************** *** 142,146 **** //build query - $sql = "UPDATE stackquestion SET questionGUID = $meta[questionGUID], questionName = $meta[questionName], --- 147,150 ---- *************** *** 148,151 **** --- 152,156 ---- questionKeywords = $meta[questionKeywords], questionUserLastEdited = $meta[lastUserEditor], + line = $meta[line], questionPublisher = $meta[questionPublisher], questionFormat = $meta[questionFormat], *************** *** 167,185 **** WHERE questionID = $id;"; ! $updated = $this->query($sql); ! if($updated) ! { ! return $id; ! } ! else ! { ! $this->errorLog->addError('Could not update Item'); ! $this->logger->critical('Failed to save item id '.$id); ! return false; ! } } /** --- 172,211 ---- WHERE questionID = $id;"; ! }*/ ! + /** + + * @param + * @return bool + * @access public + */ + public function newLine() + { + $sql = "INSERT INTO question_lines() VALUES()"; + $this->logger->debug($sql); + $this->query($sql); + + $this->query("SELECT id FROM question_lines ORDER BY id DESC LIMIT 1"); + return $this->result(0,'id'); } + public function setLatestVersion($line, $version) { + $sql = "UPDATE question_lines SET latestVersion=$version WHERE id=$line"; + $this->logger->debug("trying to set latest version with sql:$sql"); + $this->query($sql); + } + public function getLatestVersion($qid) { + $sql = "SELECT latestVersion FROM question_lines, stackquestion WHERE questionID=$qid AND line=question_lines.id"; + $this->logger->debug("trying to get latest version with sql:$sql"); + $this->query($sql); + return $this->result(0, 'latestVersion'); + } + + public function nameExists($name) { + $this->query("SELECT * FROM stackquestion WHERE questionName='$name'"); + return $this->noRows() > 0; + } /** *************** *** 207,210 **** --- 233,270 ---- } + /** + * Removes a line of items, their PRTrees and keywords + * + * @param int $id + * @return bool + * @access public + */ + public function removeLineContainingItem($id) + { + // get line from item id + $sql = "SELECT line FROM stackquestion WHERE questionID = $id"; + $result = $this->query($sql); + $line = $this->result(0, 'line'); + $this->logger->finer('Removing line '.$line); + + // get all question IDs + $sql = "SELECT questionID from stackquestion WHERE line = $line"; + $result = $this->query($sql); + if($result !== false) { + foreach($result as $row) { + $toRemove[] = $row['questionID']; + } + } + + foreach($toRemove as $id) { + $this->removeItem($id); + } + + // finally, remove line record + $sql = "DELETE FROM question_lines WHERE id = $line"; + $result = $this->query($sql); + return $result; + } + /** * Removes an items PRTrees. *************** *** 417,420 **** --- 477,518 ---- } + /** + * Returns the line that contains this Item version + * + * @param int $id + * @return int version + **/ + public function getLine($id) { + $sql = "SELECT line FROM stackquestion WHERE questionID = $id"; + //echo $sql; + $result = $this->query($sql); + if(!$result) + { + $this->logger->critical('No line recorded for item with id '.$id); + return false; + } + else + { + $toReturn = $this->result(0,'line'); + return $toReturn; + } + + } + + // returned in descending order + public function getVersions($line) { + if(!is_numeric($line)) { + $this->logger->critical("line not defined!"); + } + $sql = "SELECT questionID, questionDateLastEdited from stackquestion WHERE line=$line ORDER BY questionID DESC"; + //echo $sql; + $result = $this->query($sql); + if($result !== false) { + foreach($result as $row) { + $history[$row['questionDateLastEdited']] = $row['questionID']; + } + } + return $history; + } /** *************** *** 426,430 **** * @return array */ ! public function getListOfQuestions($userID=NULL,$public=false,$filter=NULL,$tags=NULL) { $this->logger->finest('getListOfQuestions, userID='.$userID); --- 524,528 ---- * @return array */ ! public function getListOfQuestions($userID=NULL,$public=false,$filter=NULL) { $this->logger->finest('getListOfQuestions, userID='.$userID); *************** *** 433,441 **** $qList = NULL; ! $dateFormat = stack_sqlDateFormat(true); //uses to date format in the config file to give a sql date format. ! $dateQuery = $this->conn->SQLDate($dateFormat,'questionDateLastEdited'); ! $OrderBy = ' ORDER BY questionID'; ! /* // First level if (NULL != $filter) { --- 531,538 ---- $qList = NULL; ! //$dateFormat = stack_sqlDateFormat(true); //uses to date format in the config file to give a sql date format. ! //$dateQuery = $this->conn->SQLDate($dateFormat,'questionDateLastEdited'); ! $OrderBy = ' ORDER BY questionID DESC'; // First level if (NULL != $filter) { *************** *** 456,490 **** } } - */ ! $sql = "SELECT questionID, questionName, questionDescription, valid, published, status, $dateQuery AS dateEdited " . ! "FROM stackquestion "; if(!empty($tags)) $sql .= ", question_keyword, keywords "; // tbc if($userID !== NULL) { if ($public) { ! $sql .= "WHERE (questionUserLastEdited = $userID or published=".$this->dbSafeString('Published').")"; } else { ! $sql .= "WHERE (questionUserLastEdited = $userID)"; } } ! if(!empty($tags)) { ! if($userID !== NULL) $sql .= " AND "; ! //echo '('; // create multi-keyword conditions foreach(explode(' ', $tags) as $tag) { ! $cond[] = "keywords.keyword = ".$this->dbSafeString($tag); } ! $sql .= '('.implode($cond, ' OR ').')'; ! /* ! $sql .= "keywords.keyword = ".$this->dbSafeString($tags)." " . ! "AND keywords.id = kwid " . ! "AND qid = stackquestion.questionID";*/ ! $sql .= " AND keywords.id = kwid " . ! "AND qid = stackquestion.questionID"; ! //$sql .= '('.implode($cond, ' OR ').')'; } $sql .= $OrderBy; --- 553,667 ---- } } ! $sql = "SELECT questionID, line, questionName, questionDescription, valid, published, status, questionDateLastEdited AS dateEdited " . ! "FROM stackquestion, question_lines"; if(!empty($tags)) $sql .= ", question_keyword, keywords "; // tbc if($userID !== NULL) { if ($public) { ! $sql .= " WHERE (questionUserLastEdited = $userID or published=".$this->dbSafeString('Published').")"; } else { ! $sql .= " WHERE (questionUserLastEdited = $userID)"; } } ! if($userID !== NULL) $sql .= " AND "; ! else $sql .= " WHERE "; ! $sql .= "question_lines.latestVersion = stackquestion.questionID"; ! // filter ! //if($filter !== NULL) $sql .= " AND questionName LIKE '%$filter%' "; ! ! $sql .= $OrderBy; ! ! $this->logger->debug('getListOfQuestions, sql='.$sql); ! $result = $this->query($sql); ! //print_r($sql); ! ! if($result === false) ! { ! $this->logger->error('getListOfQuestions: Failed to load question list'); ! return false; ! } ! else ! { ! global $config; ! ! $i=0; ! if($this->noRows()>0) ! { ! $dbc = new StackDBCache(); ! $dbc->connect(); ! foreach($result as $row) ! { ! $qList[$i]['id'] = $this->result($i,'questionID'); ! $qList[$i]['line'] = $this->result($i,'line'); ! $qList[$i]['questionName'] = $this->result($i,'questionName'); ! $qList[$i]['questionDescription'] = $this->result($i, 'questionDescription'); ! $qList[$i]['valid'] = $this->result($i,'valid'); ! $qList[$i]['questionDateLastEdited'] = $this->result($i,'dateEdited'); ! $qList[$i]['published'] = $this->result($i,'published'); ! $qList[$i]['status'] = $this->result($i,'status'); ! $qList[$i]['nodeployed'] = $dbc->countInstances($qList[$i]['id']); ! ! $i++; ! } ! $dbc->disconnect(); ! ! $moodleEnabled = $config->getMoodle('enabled'); ! if('true' === $moodleEnabled) ! { ! $mdb = new MoodleDB(); ! $mdb->connect(); ! foreach($qList as $key => $val){ ! $qList[$key]['moodleCategories'] = $mdb->getQuestionCategoryName($val['id']); ! } ! $mdb->disconnect(); ! } ! ! } ! return $qList; ! } ! } ! ! public function getLines($userID=NULL,$public=false,$filter=NULL,$tags=NULL) ! { ! $this->logger->finest('getLines, userID='.$userID); ! $this->logger->debug('getLines, filter='.print_r($filter, 1)); ! ! $qList = NULL; ! ! //$dateFormat = stack_sqlDateFormat(true); //uses to date format in the config file to give a sql date format. ! //$dateQuery = $this->conn->SQLDate($dateFormat,'questionDateLastEdited'); ! ! $OrderBy = ' ORDER BY questionID DESC'; ! ! $sql = "SELECT questionID, line, questionName, questionDescription, valid, published, status, questionDateLastEdited AS dateEdited " . ! "FROM stackquestion, question_lines "; ! if(!empty($tags)) $sql .= ", question_keyword, keywords "; ! if($userID !== NULL) { ! if ($public) { ! $where[] = "(questionUserLastEdited = $userID or published=".$this->dbSafeString('Published').")"; ! } else { ! $where[] = "(questionUserLastEdited = $userID)"; ! } ! } ! ! if(!empty($tags)) { // create multi-keyword conditions foreach(explode(' ', $tags) as $tag) { ! $or[] = "keywords.keyword = ".$this->dbSafeString($tag); } ! $where[] = '('.implode($or, ' OR ').')'; ! $where[] = "keywords.id = kwid AND qid = stackquestion.questionID"; } + + $where[] = "question_lines.latestVersion = stackquestion.questionID"; + + // filter + if($filter !== NULL) $where[] = "(questionName LIKE '%$filter%' OR questionDescription LIKE '%$filter%')"; + + $sql .= ' WHERE '.implode($where, ' AND '); // stitch conditions together + $sql .= $OrderBy; *************** *** 509,512 **** --- 686,690 ---- { $qList[$i]['id'] = $this->result($i,'questionID'); + $qList[$i]['line'] = $this->result($i,'line'); $qList[$i]['questionName'] = $this->result($i,'questionName'); $qList[$i]['questionDescription'] = $this->result($i, 'questionDescription'); *************** *** 515,519 **** $qList[$i]['published'] = $this->result($i,'published'); $qList[$i]['status'] = $this->result($i,'status'); - $qList[$i]['nodeployed'] = $dbc->countInstances($qList[$i]['id']); --- 693,696 ---- *************** *** 532,536 **** $mdb->disconnect(); } - } return $qList; --- 709,712 ---- *************** *** 538,547 **** } public function getQuestionsTagged($tagLine, $userID=NULL,$public=false) { $tag = $tagLine; // to explode ! $sql = "SELECT stackquestion.* from stackquestion, question_keyword, keywords " . "WHERE keywords.keyword = ".$this->dbSafeString($tag)." " . "AND keywords.id = kwid " . ! "AND qid = stackquestion.questionID"; $result = $this->query($sql); --- 714,725 ---- } + public function getQuestionsTagged($tagLine, $userID=NULL,$public=false) { $tag = $tagLine; // to explode ! $sql = "SELECT stackquestion.* from stackquestion, question_keyword, keywords, question_lines " . "WHERE keywords.keyword = ".$this->dbSafeString($tag)." " . "AND keywords.id = kwid " . ! "AND qid = stackquestion.questionID " . ! "AND qid = latestVersion"; $result = $this->query($sql); *************** *** 566,570 **** $qList[$i]['questionDescription'] = $this->result($i, 'questionDescription'); $qList[$i]['valid'] = $this->result($i,'valid'); ! $qList[$i]['questionDateLastEdited'] = $this->result($i,'dateEdited'); $qList[$i]['published'] = $this->result($i,'published'); $qList[$i]['status'] = $this->result($i,'status'); --- 744,748 ---- $qList[$i]['questionDescription'] = $this->result($i, 'questionDescription'); $qList[$i]['valid'] = $this->result($i,'valid'); ! $qList[$i]['questionDateLastEdited'] = $this->result($i,'questionDateLastEdited'); $qList[$i]['published'] = $this->result($i,'published'); $qList[$i]['status'] = $this->result($i,'status'); *************** *** 659,663 **** } } - } --- 837,840 ---- Index: StackDBMySQL.php =================================================================== RCS file: /cvsroot/stack/stack-dev/lib/database/StackDBMySQL.php,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** StackDBMySQL.php 27 Aug 2009 16:23:00 -0000 1.17 --- StackDBMySQL.php 30 Sep 2010 16:56:13 -0000 1.18 *************** *** 21,25 **** /** * MySQL connection class ! * Depricated in favour of ADOdb database connection * * @author Jonathan Hart (j.p...@bh...) --- 21,25 ---- /** * MySQL connection class ! * Deprecated in favour of ADOdb database connection * * @author Jonathan Hart (j.p...@bh...) |