-
Notifications
You must be signed in to change notification settings - Fork 3
/
maint.php
310 lines (277 loc) · 11.5 KB
/
maint.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
<?php
require_once "../config.php";
use \Tsugi\Core\LTIX;
use \Tsugi\Core\Link;
use \Tsugi\Grades\GradeUtil;
// Sanity checks
$LAUNCH = LTIX::requireData();
if ( ! $USER->instructor ) die("Requires instructor");
$p = $CFG->dbprefix;
// No Buffering
$OUTPUT->noBuffer();
// Grab our link_id
$link_id = 0;
if ( isset($_GET['link_id']) ) {
$link_id = $_GET['link_id']+0;
}
// Load to make sure it is within our context
$link_info = false;
if ( $USER->instructor && $link_id > 0 ) {
$link_info = Link::loadLinkInfo($link_id);
}
if ( $link_info === false ) die("Invalid link");
if ( isset($_POST['resetServerGrades']) ) {
$lstmt = $PDOX->queryDie(
"UPDATE {$p}lti_result SET server_grade=NULL, retrieved_at=NULL
WHERE link_id = :LID",
array(":LID" => $link_id)
);
$msg = $lstmt->rowcount() . " Records reset.";
$_SESSION["success"] = $msg;
header("Location: ".addSession('maint.php?link_id='.$link_id));
return;
}
if ( isset($_POST['getServerGrades']) ) {
$row = $PDOX->rowDie(
"SELECT COUNT(*) AS count FROM {$p}lti_result AS R
JOIN {$p}lti_service AS S ON R.service_id = S.service_id
WHERE link_id = :LID AND grade IS NOT NULL AND
(server_grade IS NULL OR retrieved_at < R.updated_at) AND
(( sourcedid IS NOT NULL AND service_key IS NOT NULL ) OR result_url IS NOT NULL )",
array(":LID" => $link_id)
);
$total = $row['count'];
if ( $total == 0 ) {
$_SESSION['success'] = 'No records remain to retrieve';
header("Location: ".addSession('maint.php?link_id='.$link_id));
return;
}
$OUTPUT->header();
echo($OUTPUT->togglePreScript());
session_write_close();
echo("</head><body>\n");
echo("Records to be processed: ".$total."<br/>");
flush();
$stmt = $PDOX->queryDie(
"SELECT result_id, result_url, sourcedid, service_key FROM {$p}lti_result AS R
JOIN {$p}lti_service AS S ON R.service_id = S.service_id
WHERE link_id = :LID AND grade IS NOT NULL AND
(server_grade IS NULL OR retrieved_at < R.updated_at) AND
(( sourcedid IS NOT NULL AND service_key IS NOT NULL ) OR result_url IS NOT NULL )",
array(":LID" => $link_id)
);
$count = 0;
$success = 0;
$begin = microtime(true);
$fail = 0;
while ( $row = $stmt->fetch(PDO::FETCH_ASSOC) ) {
$count = $count + 1;
$start = microtime(true);
// UPDATEs automatically on success
$grade = LTIX::gradeGet($row);
$et = (microtime(true) - $start) ;
$ets = sprintf("%1.3f",$et);
if ( is_string($grade) ) {
$fail++;
$OUTPUT->togglePre("Error at ".$count.' / '.$total.' ('.$ets.')'.' '.$row['service_key'],$grade);
flush();
} else {
$success++;
// echo("Grade=".$grade."<br/>\n");
// print_r($row); echo("<br/>\n");
if ( $success % 10 == 0 ) {
echo("Grade=$grade ($ets) $count / $total <br/>\n");
flush();
}
}
if ( $count > 1000 ) break;
}
// unset($_SESSION['error']);
$et = (microtime(true) - $begin) ;
$ets = sprintf("%1.3f",$et);
$msg = $count . " Records processed ".$ets." seconds. success=".$success.' fail='.$fail;
echo($msg."<br/>\n");
echo('<script type="text/javascript"> alert("Retrieve Server Grades Complete"); </script>');
return;
}
if ( isset($_POST['fixServerGrades']) ) {
$OUTPUT->header();
echo($OUTPUT->togglePreScript());
echo("</head><body>\n");
session_write_close();
$stmt = $PDOX->queryDie(
"SELECT result_id, result_url, link_id, grade, server_grade, note,
sourcedid, service_key,
U.user_id AS user_id, displayname, email
FROM {$p}lti_result AS R
JOIN {$p}lti_service AS S ON R.service_id = S.service_id
JOIN {$p}lti_user AS U ON R.user_id = U.user_id
WHERE link_id = :LID AND grade IS NOT NULL AND
server_grade IS NOT NULL AND
server_grade < grade AND
(( sourcedid IS NOT NULL AND service_key IS NOT NULL ) OR result_url IS NOT NULL )",
array(":LID" => $link_id)
);
$count = 0;
$success = 0;
$fail = 0;
while ( $row = $stmt->fetch(PDO::FETCH_ASSOC) ) {
echo(htmlent_utf8($row['displayname']));
echo(' (');
echo(htmlent_utf8($row['email']));
echo(') ');
echo("local=".$row['grade']." server=".$row['server_grade']);
echo("<br/>\n");
$count = $count + 1;
$debug_log = array();
$status = LTIX::gradeSend($row['grade'], $row, $debug_log); // This is the slow bit
if ( $status === true ) {
echo('Grade submitted to server'."<br/>\n");
$success++;
} else {
echo('<pre class="alert alert-danger">'."\n");
$msg = "result_id=".$row['result_id']."\n".
"grade=".$row['grade']." server_grade=".$row['server_grade']."\n".
"error=".$status;
echo_log("Problem Sending Grade: ".session_id()."\n".$msg."\n".
"result_url=".$row['reult_url'].
" service_key=".$row['service_key']." sourcedid=".$row['sourcedid']);
echo("</pre>\n");
$OUTPUT->togglePre("Error retrieving new grade at ".$count,$LastPOXGradeResponse);
flush();
echo("Problem sending grade ".$status."<br/>\n");
$fail++;
continue;
}
// Check to see if the grade we sent is really there - Also updates our local table
$server_grade = LTIX::gradeGet($row);
if ( is_string($server_grade) ) {
echo('<pre class="alert alert-danger">'."\n");
$msg = "result_id=".$row['result_id']."\n".
"grade=".$row['grade']." updated=".$row['updated_at']."\n".
"server_grade=".$row['server_grade']." retrieved=".$row['retrieved_at']."\n".
"error=".$server_grade;
echo_log("Problem Updating Grade: ".session_id()."\n".$msg."\n".
"result_url=".$row['reult_url'].
" service_key=".$row['service_key']." sourcedid=".$row['sourcedid']);
echo("</pre>\n");
error_log("Error re-retrieving grade: ".session_id().' result_id='.$row['result_id'].
"result_url=".$row['reult_url'].
' sourcedid='+$row['sourcedid']+' service_key='+$row['service_key']);
$OUTPUT->togglePre("Error retrieving new grade at ".$count,$LastPOXGradeResponse);
flush();
$fail++;
continue;
} else if ( $server_grade != $row['grade'] ) {
} else {
}
if ( $success % 10 == 0 ) {
echo("Grade=$grade ($ets) $count / $total <br/>\n");
flush();
}
}
$msg = $count . " Mis-matched grade entries. fixed=$success fail=$fail";
echo($msg."<br/>\n");
echo('<script type="text/javascript"> alert("Fix Mis-matched Grades Complete"); </script>');
return;
}
// View
$OUTPUT->header();
?>
<script type="text/javascript">
function showFrame() {
$('#my_iframe').prop('src', '<?php echo($CFG->wwwroot.'/mod/grades/blank.html'); ?>');
document.getElementById('iframediv').style.display = "block";
$('#clear').show();
}
</script>
<?php
$OUTPUT->bodyStart();
$OUTPUT->flashMessages();
$iframeurl = addSession('maint.php?link_id=' . $link_id);
?>
<div>
<form style="display: inline" method="post" target="my_iframe" action="<?php echo($iframeurl); ?>">
<button name="fixServerGrades" onclick="showFrame();" class="btn btn-warning">Fix Mis-matched Grades</button>
<button name="getServerGrades" onclick="showFrame();" class="btn btn-warning">Retrieve Server Grades</button>
</form>
<form method="post" style="display: inline">
<button name="resetServerGrades"
onclick="return confirm('Are you sure you want to clear out all of the previously retrieved server grades?');"
class="btn btn-danger">Reset Local Server Grades</button>
<a href="#" id="clear" style="display: none" onclick="
$('#my_iframe').prop('src', '<?php echo($CFG->wwwroot.'/mod/grades/blank.html'); ?>');return false;"
class="btn btn-primary">Clear/Stop Frame</a>
<button onclick="window.close();" class="btn btn-primary">Exit</button>
</div>
<p>These are maintenance tools make sure you know how to use them.
<ul>
<li><b>Fix Mis-matched Grades</b> copies our local grade to the server
when there is a mismatch between the local grade and our most recent
server grade. It is quick unless there are a lot of mis-matches.
</li>
<li><b>Retrieve Server Grades</b> calls a web service to pul down a
copy of the grade stored in the server that have not yet
been retrieved. This process takes abut 0.3 seconds per "grade to retrieve".
</li>
<li><b>Reset Local Server Grades</b> - resets the local
copies of server grades so that the next <b>Retrieve Server Grades</b>
will retrieve all grades.</li>
</ul>
<pre>
Context: <?php echo($CONTEXT->id);
if ( isset($CONTEXT->title) ) echo(' '.htmlent_utf8($CONTEXT->title)) ; ?>
Link id: <?php echo($link_id);
if ( isset($link_info['title']) ) echo(' '.htmlent_utf8($link_info['title'])) ; ?>
</pre>
<p><b>Total results:</b> <span id="total"><img src="<?php echo($OUTPUT->getSpinnerUrl()); ?>"></span>
<img id="totspinner" src="<?php echo($OUTPUT->getSpinnerUrl()); ?>" style="display:none">
</p>
<p><b>Grades to Retrieve:</b> <span id="toretrieve"><img src="<?php echo($OUTPUT->getSpinnerUrl()); ?>"></span>
<img id="retspinner" src="<?php echo($OUTPUT->getSpinnerUrl()); ?>" style="display:none">
</p>
<p><b>Mis-matched Grades:</b> <span id="mismatch"><img src="<?php echo($OUTPUT->getSpinnerUrl()); ?>"></span>
<img id="misspinner" src="<?php echo($OUTPUT->getSpinnerUrl()); ?>" style="display:none">
</p>
<div id="iframediv" style="display:none">
<p>Depending on buffering - output in this iframe may take a while to appear.
Once the output starts, make sure to scroll to the bottom to see the current activity.
The number of grades to retrieve will be updated above even if you do
not see output below. Is you want to abort this job, press
"Clear/Stop" and be a little patient. This job may take so long it times out.
That is OK - simply come back and restart it - it will pick up where it left off.
</p>
<iframe id="my_iframe" width="98%" height="600px" style="border: 1px black solid">
</iframe>
</div>
<?php
$OUTPUT->footerStart();
?>
<script type="text/javascript">
$UPDATE_INTERVAL = false;
function updateNumbers() {
window.console && console.log('Calling updateNumbers');
$.ajaxSetup({ cache: false }); // For IE...
$.getJSON('<?php echo(addSession('maintcount.php?link_id='.$link_id)); ?>',
function(data) {
if ( $UPDATE_INTERVAL === false ) $UPDATE_INTERVAL = setInterval(updateNumbers,10000);
window.console && console.log(data);
$('#totspinner').hide();
$('#retspinner').hide();
$('#misspinner').hide();
oldtotal = $('#total').text();
window.console.log("old="+oldtotal);
$('#total').text(data.total);
if ( oldtotal.length > 1 && oldtotal != data.total ) $('#totspinner').show();
oldtoretrieve = $('#toretrieve').text();
$('#toretrieve').text(data.toretrieve);
if ( oldtoretrieve.length > 1 && oldtoretrieve != data.toretrieve ) $('#retspinner').show();
oldmismatch = $('#mismatch').text();
$('#mismatch').text(data.mismatch);
if ( oldmismatch.length > 1 && oldmismatch != data.mismatch ) $('#misspinner').show();
});
}
updateNumbers();
</script>
<?php
$OUTPUT->footerEnd();