/[libdata]/trunk/admin/include/scribe_fix.php
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/admin/include/scribe_fix.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (hide annotations)
Thu Mar 4 22:43:50 2004 UTC (20 years, 1 month ago) by dpavlin
File size: 18984 byte(s)
rename all mysql_ functions to xx_ so that wrapper can be used

1 dpavlin 1 <?php
2     /**********************************************************
3     Function Library: scribe_fix.php
4     Original Author: Paul Bramscher <brams006@tc.umn.edu>
5     Last Modified: 10.29.2003
6     ***********************************************************
7     Comments:
8     This library brings together CourseLib/PageScribe page
9     debugging and fixing algorithms.
10     ***********************************************************
11     errorTrap
12     genCalc
13     isOrphan
14     purgeOrphans
15     purgeRelationships
16     scribeFix
17     updateGenerations
18     updateOrders
19     updateOrphans
20     **********************************************************/
21    
22     /**********************************************************
23     Function: errorTrap
24     Author: Paul Bramscher
25     Last Modified: 10.28.2003
26     ***********************************************************
27     Purpose:
28     Debugger available for CLPS system, to check for various
29     sorts of page integrity. If page_debug in the page table
30     is equal to 1, then this function is useful to call from
31     scribe.phtml automatically. Otherwise, it's called
32     manually from the DBA console.
33     **********************************************************/
34     function errorTrap($con, $page_id){
35    
36     // Fetch title
37     $page_title = lookupField($con, "page", "page_id", $page_id, "page_title");
38    
39     // Overall status
40     $passed = 1;
41    
42     printf("<center>\n");
43     printf("<table width=\"90%%\" class=\"backLight\" border=\"1\">\n");
44     printf("<tr><td class=\"cellPlain\">Debug Data: %s (#%d)</td></tr>\n", $page_title, $page_id);
45     printf("<tr><td><br>\n");
46    
47     /***********************
48     ** Basic Element Data **
49     ***********************/
50    
51     printf("<b>Element Data:</b><br>");
52    
53     // Distinct orders
54     $sql = "SELECT DISTINCT element_order FROM element WHERE page_id ="
55     . $page_id;
56 dpavlin 42 $rs = xx_query($sql, $con);
57     $num_orders = xx_num_rows($rs);
58 dpavlin 1 printf("Unique orders: %d<br>\n", $num_orders);
59    
60     // Number of rows (should be the same)
61     $sql = "SELECT element_id FROM element WHERE page_id = "
62     . $page_id;
63 dpavlin 42 $rs = xx_query($sql, $con);
64     $num_rows = xx_num_rows($rs);
65 dpavlin 1 printf("Number of rows: %d<BR>\n", $num_rows);
66    
67     // Smallest order (if rows present, should be 1)
68     $sql = "SELECT MIN(element_order) as min_order FROM element WHERE page_id = "
69     . $page_id;
70 dpavlin 42 $rs = xx_query($sql, $con);
71     $row = xx_fetch_array ($rs);
72 dpavlin 1 $min_order = $row["min_order"];
73     printf("First order: %d<br>\n", $min_order);
74    
75     // Largest order (should equal distinct rows and number of rows
76     $sql = "SELECT MAX(element_order) as max_order FROM element WHERE page_id = "
77     . $page_id;
78 dpavlin 42 $rs = xx_query($sql, $con);
79     $row = xx_fetch_array ($rs);
80 dpavlin 1 $max_order = $row["max_order"];
81     printf("Last order: %d<br><br>\n", $max_order);
82    
83     /************************************
84     ** Child-to-Parent reference check **
85     ************************************/
86    
87     printf("<b>Child-to-Parent reference check:</b><br>\n");
88     $c1_sql = "SELECT element_id, parent_id, element_order, indent_level FROM element WHERE page_id = "
89     . $page_id
90     . " AND parent_id > 0 ORDER BY element_order";
91 dpavlin 42 $c1_rs = xx_query($c1_sql, $con);
92 dpavlin 1
93 dpavlin 42 while ($c1_row = xx_fetch_array ($c1_rs)) {
94 dpavlin 1 $parent_id = $c1_row["parent_id"];
95     $indent_level = $c1_row["indent_level"];
96     $element_id = $c1_row["element_id"];
97     $element_order = $c1_row["element_order"];
98    
99     // For each row returned, hunt for the parent
100     $c2_sql ="SELECT element_id, element_order, indent_level FROM element WHERE element_id = "
101     . $parent_id;
102 dpavlin 42 $c2_rs = xx_query($c2_sql, $con);
103     $c2_row = xx_fetch_array ($c2_rs);
104 dpavlin 1 $c2_indent_level = $c2_row["indent_level"];
105     $c2_element_id = $c2_row["element_id"];
106     $c2_element_order = $c2_row["element_order"];
107    
108     if (!($c2_element_id > 0)) {
109     $passed = 0;
110     printf("Failed. child element #%d tried to reference non-existent element #%d as parent.<br>\n", $element_id, $parent_id);
111     }
112    
113     if (!($c2_element_order < $element_order)) {
114     $passed = 0;
115     printf("Failed. child element #%d tried to reference later-occuring element #%d as parent.<br>\n", $element_id, $parent_id);
116     }
117    
118     if (!($c2_indent_level == ($indent_level - 1))) {
119     $passed = 0;
120     printf("Failed. child element #%d is not exactly one generation older than parent element #%d.<br>\n", $element_id, $parent_id);
121     }
122    
123     }
124     if ($passed == 1) printf("Passed.<br>\n");
125     printf("<BR>\n");
126    
127     /*************************
128     ** Order integrity test **
129     *************************/
130    
131     printf("<b>Order integrity test:</b><br>\n");
132     printf("Order uniqueness check: ");
133     if ($num_orders == $num_rows) printf("Passed");
134     else {
135     printf("Failed");
136     $passed = 0;
137     }
138     printf("<BR>\n");
139    
140     printf("Order start at 1 check: ");
141     if ($num_rows > 0) {
142     if ($min_order == 1) printf("Passed");
143     else {
144     printf("Failed");
145     $passed = 0;
146     }
147     }
148     else printf("(Empty page)");
149     printf("<br>\n");
150    
151     printf("Order max %d check: ", $num_rows);
152     if ($num_rows == $num_orders && $num_rows == $max_order) printf ("passed");
153     else {
154     printf("Failed");
155     $passed = 0;
156     }
157     printf("<br><br>\n");
158    
159     /***********************************************************************
160     * Compare given indent level with the calculated/traversed equivalent. *
161     ***********************************************************************/
162    
163     printf("<b>Generation traversal tests:</b><br> ");
164     $passed_gen = 1;
165     $sql = "SELECT
166     element_id,
167     parent_id,
168     indent_level
169     FROM
170     element
171     WHERE page_id = "
172     . $page_id
173     . " ORDER BY element_order";
174    
175 dpavlin 42 $rs = xx_query($sql, $con);
176 dpavlin 1
177 dpavlin 42 while ($row = xx_fetch_array ($rs)) {
178 dpavlin 1 $element_id = $row["element_id"];
179     $indent_level = $row["indent_level"];
180     $parent_id = $row["parent_id"];
181     $gen_level = 0;
182    
183     // Call the generational calculator for each element
184     $gen_level = genCalc($con, $element_id, $gen_level, $page_id, $parent_id);
185    
186     if ($gen_level != $indent_level) {
187     printf("Failed. Element ID#%d reported generation of %d, but calculated at %d.<BR>\n", $element_id, $indent_level, $gen_level);
188     $passed = 0;
189     $passed_gen = 0;
190     }
191    
192     // printf("Given indent was %s, gen calc. was %s<BR>", $indent_level, $gen_level);
193    
194     }
195     if ($passed_gen == 1) printf("Passed.<br>\n");
196     else printf("Failed one or more generation calculations.<br>\n");
197    
198     printf("<br>\n");
199    
200     printf("<b>Final Summary:</b><br>");
201     if ($passed == 1) printf("This page appears to be bug-free.");
202     else printf("This page failed one or more tests.");
203    
204     // Close the table
205     printf("<br><br></td></tr></table>\n");
206    
207     printf("</center>\n");
208    
209     return $passed;
210    
211     }
212    
213    
214     /**********************************************************
215     Function: genCalc
216     Author: Paul Bramscher
217     Last Modified: 10.27.2003
218     ***********************************************************
219     Purpose:
220     Recursively calculate the traversable generational level of
221     the given element id. If this figure is not equal to its
222     indent level, then there's an error. The fix algorithm
223     will update the indent_level value in the elements table
224     with the calculated value determined here.
225     **********************************************************/
226     function genCalc($con, $element_id, $gen_level, $page_id, $parent_id) {
227    
228     // If there is a parent to probe
229     if ($parent_id > 0) {
230    
231     // See if the parent actually exists
232     $sql = "SELECT element_id, parent_id
233     FROM element
234     WHERE element_id = "
235     . $parent_id
236     . " AND page_id = "
237     . $page_id;
238    
239 dpavlin 42 $rs = xx_query($sql, $con);
240     $row = xx_fetch_array ($rs);
241 dpavlin 1 $probe_parent_id = $row["parent_id"];
242     $probe_element_id = $row["parent_id"];
243    
244     // See if the probed element has any parents to probe further
245     if ($probe_element_id > 0) {
246     return 1 + genCalc($con, $probe_element_id, $gen_level, $page_id, $probe_parent_id);
247    
248     }
249    
250     // No more parents
251     return 1;
252    
253     }
254    
255     return 0;
256    
257     }
258    
259    
260     /**********************************************************
261     Function: isOrphan
262     Author: Paul Bramscher
263     Last Modified: 08.27.2003
264     ***********************************************************
265     Purpose:
266     Determines if the supplied PageScribe/CourseLib element is
267     an orphaned type element. To be a valid child, a parent must
268     (a) exist, (b) appear earlier in the order of elements
269     1-N on a page, and (c) appear only once. If any criteria
270     fails, the element is said to be orphaned, a bastard or
271     otherwise of problematic ancestry.
272     **********************************************************/
273     function isOrphan($con, $element_id, $element_order, $page_id, $parent_id) {
274    
275     //Initialize
276     $orphan = 0;
277    
278     if ($parent_id > 0) {
279    
280     // First determine if the parent exists.
281     $sql = "SELECT count(*) as par_found
282     FROM element
283     WHERE page_id = "
284     . $page_id
285     . " AND element_id = "
286     . $parent_id
287     . " AND element_order < "
288     . $element_order;
289    
290     // testing
291     // printf("orphan probe sql was: %s ", $sql);
292    
293 dpavlin 42 $rs = xx_query($sql, $con);
294     $row = xx_fetch_array ($rs);
295 dpavlin 1 $par_found = $row["par_found"];
296    
297     // Should have only one match. If none (or multiple) set to 0.
298     if ($par_found == 1) $orphan = 0;
299     else $orphan = 1;
300    
301     // Output
302     if ($orphan == 1) printf("Found orphan: ID#%d.<br>", $element_id);
303    
304     }
305    
306     return $orphan;
307     }
308    
309    
310     /**********************************************************
311     Function: purgeOrphans
312     Author: Paul Bramscher
313     Last Modified: 10.28.2003
314     ***********************************************************
315     Purpose:
316     Purges and orphans found on the page.
317     **********************************************************/
318    
319     function purgeOrphans($con, $page_id) {
320    
321     printf("<b>Method #2 Delete fostered children and their descendants</b><br><br>\n");
322     printf("<b>Messages:</b><br>\n");
323    
324     // Walk through all elements on the page
325     $sql = "SELECT
326     element_id,
327     element_order,
328     parent_id
329     FROM element
330     WHERE page_id = "
331     . $page_id
332     . " ORDER BY element_order";
333    
334 dpavlin 42 $rs = xx_query($sql, $con);
335 dpavlin 1
336 dpavlin 42 while ($row = xx_fetch_array ($rs)) {
337 dpavlin 1 $element_id = $row["element_id"];
338     $element_order = $row["element_order"];
339     $parent_id = $row["parent_id"];
340    
341     /* If an orphan, delete it and its first generation.
342     Recall some Egyptian/Biblical curse here.*/
343    
344     if ($parent_id > 0 && isOrphan($con, $element_id, $element_order, $page_id, $parent_id)) {
345    
346     $sub_sql = "DELETE FROM element
347     WHERE page_id = "
348     . $page_id
349     . " AND element_id = "
350     . $element_id
351     . " AND parent_id = "
352     . $parent_id;
353    
354     // printf("delete sql wasd: %s<BR>", $sql);
355    
356 dpavlin 42 if (!xx_query ($sub_sql, $con)){
357 dpavlin 1 sql_err($sub_sql);
358 dpavlin 42 xx_query ("UNLOCK TABLES", $con);
359 dpavlin 1 bailout();
360     }
361     else {
362    
363     // Output
364     printf("Element %d was an orphan. Deleted it.<br>\n", $element_id);
365    
366 dpavlin 42 xx_query ("UNLOCK TABLES", $con);
367 dpavlin 1 } // deleted this element
368    
369     } // delete all elements which are orphaned
370    
371     } // for all elements with parents specified, check if they are orphaned
372    
373     } // end purgeOrphans
374    
375    
376     /**********************************************************
377     Function: purgeRelationships
378     Author: Paul Bramscher
379     Last Modified: 10.28.2003
380     ***********************************************************
381     Purpose:
382     Purges all parent-child relationships on the page, and
383     reduces all elements to root-level elements. Highly
384     destructive, but virtually guaranteed to fix a page.
385     **********************************************************/
386    
387     function purgeRelationships($con, $page_id) {
388    
389     printf("<b>Method #3 Purge all parent-child relationships!</b><br><br>\n");
390     printf("<b>Messages:</b><br>\n");
391    
392     $sql = "UPDATE element
393     SET parent_id = 0, indent_level = 0
394     WHERE page_id = "
395     . $page_id;
396    
397 dpavlin 42 if (!xx_query ($sql, $con)){
398 dpavlin 1 sql_err($sql);
399 dpavlin 42 xx_query ("UNLOCK TABLES", $con);
400 dpavlin 1 bailout();
401     }
402     else {
403    
404     printf("Purged all!<br>\n");
405 dpavlin 42 xx_query ("UNLOCK TABLES", $con);
406 dpavlin 1 } // purged all!
407    
408    
409     } // end purgeRelationships
410    
411    
412     /**********************************************************
413     Function: scribeFix
414     Author: Paul Bramscher
415     Last Modified: 10.28.2003
416     ***********************************************************
417     Purpose:
418     Fixes a broken PageScribe/CourseLib page based on best
419     guess. Methods:
420     (1) Attach foster children (and their descendants)
421     to most likely parent: first previous parent.
422     (2) Delete foster children (and their descendants).
423     (3) Delete all parent-child relationships, and convert all
424     elements to root-level (guaranteed fix).
425    
426     Required steps, automatically followed after any method:
427     (a) First element is 1, Nth element must be N
428     (b) Fill in any "holes" in the element order.
429     (c) Clean up all indent levels.
430     **********************************************************/
431     function scribeFix($con, $method, $page_id){
432    
433     printf("<center>\n");
434     printf("<table width=\"90%%\" class=\"backLight\" border=\"1\">\n");
435     printf("<tr><td class=\"cellPlain\">Page Fix Dialog (#%d)</td></tr>\n", $page_id);
436     printf("<tr><td><br>\n");
437    
438     switch ($method) {
439    
440     // Update orphans
441     case 1: updateOrphans($con, $page_id);
442     break;
443    
444     // Purge orphans
445     case 2: purgeOrphans($con, $page_id);
446     break;
447    
448     // Purge all parent-child relationships
449     case 3: purgeRelationships($con, $page_id);
450     break;
451    
452     default:
453     break;
454    
455     }
456    
457     // Required cleanup, regardless of fix methodology
458     updateOrders($con, $page_id);
459     updateGenerations($con, $page_id);
460    
461     printf("<br>Done. Re-run the debugger against this page to determine success: <a href=\"scribe_debug.phtml?page_id=%d\">Debug Page ID#%d</a><br><br>", $page_id, $page_id);
462     printf("</td></tr></table></center>\n");
463    
464    
465     } // end scribeFix
466    
467    
468     /**********************************************************
469     Function: updateGenerations
470     Author: Paul Bramscher
471     Last Modified: 10.28.2003
472     ***********************************************************
473     Purpose:
474     Walks through a page and compares calculated generation with
475     reported indent level. When a discrepancy is found, fix it
476     according to the calculated generation.
477     **********************************************************/
478     function updateGenerations($con, $page_id) {
479    
480     printf("<br><b>Analyzing generational structure:</b><br>\n");
481    
482     // Initialize
483     $passed_gen = 1;
484     $element_count = 0;
485    
486     // Load all elements on the page
487     $sql = "SELECT
488     element_id,
489     parent_id,
490     indent_level
491     FROM
492     element
493     WHERE page_id = "
494     . $page_id
495     . " ORDER BY element_order";
496    
497 dpavlin 42 $rs = xx_query($sql, $con);
498 dpavlin 1
499 dpavlin 42 while ($row = xx_fetch_array ($rs)) {
500 dpavlin 1 $element_id = $row["element_id"];
501     $indent_level = $row["indent_level"];
502     $parent_id = $row["parent_id"];
503    
504     // Initialize
505     $gen_level = 0;
506    
507     // Call the generational calculator for each element
508     $gen_level = genCalc($con, $element_id, $gen_level, $page_id, $parent_id);
509    
510     // A discrepancy was founnd
511     if ($gen_level != $indent_level) {
512    
513     // MArk as failed
514     $passed_gen = 0;
515    
516     // Reset the indent levels
517     $sub_sql = "UPDATE element
518     SET indent_level = "
519     . $gen_level
520     . " WHERE page_id = "
521     . $page_id
522     . " AND element_id = "
523     . $element_id;
524    
525 dpavlin 42 if (!xx_query ($sub_sql, $con)){
526 dpavlin 1 sql_err($sub_sql);
527 dpavlin 42 xx_query ("UNLOCK TABLES", $con);
528 dpavlin 1 bailout();
529     }
530     else {
531     // Output
532     printf("Element #%d reported generation of %d, but calculated at %d. Fixed.<br>\n", $element_id, $indent_level, $gen_level);
533 dpavlin 42 xx_query ("UNLOCK TABLES", $con);
534 dpavlin 1
535     } // fixed this element's indent
536    
537     } // if there is a discrepancy with calculated generation level
538    
539     } // for all elements, calculate and fix (if needed) their indents
540    
541     if ($passed_gen == 1) printf("No generational errors found.<br>\n");
542    
543     } // end updateGenerations
544    
545    
546     /**********************************************************
547     Function: updateOrders
548     Author: Paul Bramscher
549     Last Modified: 10.28.2003
550     ***********************************************************
551     Purpose:
552     Walks through a page and compares calculated order with
553     reported order. When a discrepancy is found, fix it
554     according to the calculated order.
555     **********************************************************/
556     function updateOrders($con, $page_id) {
557    
558     printf("<br><b>Analyzing cardinal orders:</b><br>\n");
559    
560     // Initialize
561     $passed_card = 1;
562     $element_count = 0;
563    
564     // Cycle through all elements on the page
565     $sql = "SELECT
566     element_id,
567     element_order
568     FROM
569     element
570     WHERE page_id = "
571     . $page_id
572     . " ORDER BY element_order";
573    
574 dpavlin 42 $rs = xx_query($sql, $con);
575 dpavlin 1
576 dpavlin 42 while ($row = xx_fetch_array ($rs)) {
577 dpavlin 1 $element_id = $row["element_id"];
578     $element_order = $row["element_order"];
579    
580     // Increment row counter
581     $element_count++;
582    
583     // If there's an order problem, do this
584     if ($element_count != $element_order) {
585    
586     // Mark as failed
587     $passed_card = 0;
588    
589     // Reset the order
590     $sub_sql = "UPDATE element
591     SET element_order = "
592     . $element_count
593     . " WHERE page_id = "
594     . $page_id
595     . " AND element_id = "
596     . $element_id;
597    
598 dpavlin 42 if (!xx_query ($sub_sql, $con)){
599 dpavlin 1 sql_err($sub_sql);
600 dpavlin 42 xx_query ("UNLOCK TABLES", $con);
601 dpavlin 1 bailout();
602     }
603     else {
604    
605     // Output
606     printf("Row #%d reported cardinal order of %d, but calculated at %d. Fixed.<br>\n", $element_count, $element_order, $element_count);
607 dpavlin 42 xx_query ("UNLOCK TABLES", $con);
608 dpavlin 1 } // fixed this element's order
609    
610     } // if an order discrepancy was found
611    
612     } // for all elements, check their orders and fix (if needed)
613    
614     // If no problems found
615     if ($passed_card == 1) printf("No cardinal order errors found.<br>\n");
616    
617     } // end updateOrders
618    
619    
620     /**********************************************************
621     Function: updateOrphans
622     Author: Paul Bramscher
623     Last Modified: 10.28.2003
624     ***********************************************************
625     Purpose:
626     Walks through a page and hunts for orphaned/bastard
627     children. Hunts for most likely parent and attaches the
628     child to it.
629     **********************************************************/
630     function updateOrphans($con, $page_id) {
631    
632     // Initialize
633     $passed_orphan = 1;
634    
635     printf("<b>Method #1 Attach orphans to a foster parent</b><br><br>\n");
636     printf("<b>Messages:</b><br>\n");
637    
638     $sql = "SELECT
639     element_id,
640     element_order,
641     parent_id,
642     indent_level
643     FROM element
644     WHERE page_id = "
645     . $page_id
646     . " ORDER BY element_order";
647    
648 dpavlin 42 $rs = xx_query($sql, $con);
649 dpavlin 1
650 dpavlin 42 while ($row = xx_fetch_array ($rs)) {
651 dpavlin 1 $element_id = $row["element_id"];
652     $element_order = $row["element_order"];
653     $parent_id = $row["parent_id"];
654     $indent_level = $row["indent_level"];
655    
656     $new_parent_id = parentProbe($con, $page_id, $element_order, $indent_level);
657     $orphaned = 0;
658     $orphaned = isOrphan($con, $element_id, $element_order, $page_id, $parent_id);
659    
660     // Hunt for most likely parent, and assign to it instead.
661     if ($parent_id > 0 && $orphaned == 1) {
662    
663     // Mark as failed
664     $passed_orphan = 0;
665    
666     $sub_sql = "UPDATE element
667     SET parent_id = "
668     . $new_parent_id
669     . " WHERE page_id = "
670     . $page_id
671     . " AND element_id = "
672     . $element_id;
673    
674 dpavlin 42 if (!xx_query ($sub_sql, $con)){
675 dpavlin 1 sql_err($sub_sql);
676 dpavlin 42 xx_query ("UNLOCK TABLES", $con);
677 dpavlin 1 bailout();
678     }
679     else {
680    
681     // Output
682     printf("Element #%d orphaned. Reassigned to parent #%d<br>\n", $element_id, $new_parent_id);
683    
684 dpavlin 42 xx_query ("UNLOCK TABLES", $con);
685 dpavlin 1 } // reassigned this element
686    
687     } // reassign problematic elements
688    
689     } // for all elements with a problematic ancestry, find a most likely parent
690    
691     if ($passed_orphan == 1) printf("No orphans found.<br>\n");
692    
693     } // end updateOrphans
694     ?>

  ViewVC Help
Powered by ViewVC 1.1.26