/[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 72 - (hide annotations)
Thu Mar 18 20:33:37 2004 UTC (20 years, 1 month ago) by dpavlin
File size: 17997 byte(s)
changes made in version 2.00

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

  ViewVC Help
Powered by ViewVC 1.1.26