University of Southern California

api1c.php

00001 <?php
00012 require_once("WSCORE2.php");
00013 require_once("soc1c.php");
00014 require_once("ais_soap1c.php");
00015 
00016 function debug($msg) {
00017   $fp = fopen('/www/ws/soc/debug-log/debug.log','a');
00018   fwrite($fp, date('Y-m-d H:i:s') . ' -> ' . $msg . PHP_EOL);
00019   fclose($fp);
00020 }
00021 
00036 class SOC_API1C extends SOC_Widget {
00043   function __construct($conf) {
00044     SOC_Widget::SOC_Widget($conf);
00045     $this->version_msg = "SOC API1C";
00046     $this->cache = new SOC_Cache2($this);
00047     $this->cache->open();
00048     $this->service = "";
00049     if ($this->get("soc_path")) {
00050         $filename = $this->get("soc_path") . '/data/dept-urls.json';
00051     } else {
00052         $filename = "data/dept-urls.json";
00053     }
00054     if (file_exists($filename)) {
00055         $this->dept_info = json_decode(file_get_contents($filename), true);
00056     } else {
00057         $this->dept_info = array();
00058     }
00059   }
00060 
00064   public function close () {
00065   return $this->cache->close();
00066   }
00067 
00074   function _restParse ($restful_args) {
00075     $args = explode('/',trim($restful_args));
00076     if (count($args) < 2) {
00077       $this->error("Not sure what you want me to do [$restful_args]");
00078     }
00079     $i = 1; // Index we're working on.
00080     if (isset($args[$i])) {
00081       $object = strtolower($args[$i]);
00082       // Figure out the output format, content type and initial content.
00083       switch($object) {
00084         case 'help':
00085           $this->format = "html";
00086           $this->content_type = "text/html";
00087           break;
00088         default:
00089           // Set the default content type and format
00090           //$this->content_type = "text/plain";
00091           $this->content_type = "application/json";
00092           $this->format = "json";
00093           break;
00094       }
00095     }
00096 
00097     // Figure out the service we're accessing
00098     if (isset($args[$i])) {
00099       $object = strtolower($args[$i]);
00100       $this->service = $object;
00101       switch($object) {
00102         case 'session':
00103           $this->service = 'session';
00104           $i++;
00105           if (isset($args[$i])) {
00106             $this->set("active_session",$args[$i]);
00107           } else {
00108             $this->error("Must include a session code. e.g. 001, 002, 003");
00109           }
00110           $i++;
00111           if (isset($args[$i])) {
00112             $this->set("active_term",$args[$i]);
00113           } else {
00114             $this->error("Must include a term code. e.g. 20091 for Spring 2009, 20092 for Summer 2009, 20093 for Fall 2009");
00115           }
00116           break;
00117         case 'classes':
00118           $this->service = 'classes';
00119           $i++;
00120           if (isset($args[$i])) {
00121             $this->set("active_dept",$args[$i]);
00122             $i++;
00123           } else {
00124             $this->error("You need to provide a department for your request.  e.g. ".$this->get("soc_uri")."/api1c/classes/hist/20091 would request classes offered by the History department for Spring 2009");
00125           }
00126           if (isset($args[$i])) {
00127             $this->set("active_term",$args[$i]);
00128             $i++;
00129           } else {
00130             $this->error("You need to provide a term for your request.  e.g. ".$this->get("soc_uri")."/api1c/classes/hist/20091 would request classes offered by the History department for Spring 2009");
00131           }
00132           break;
00133         case 'departments':
00134         case 'depts':
00135           $this->service = 'departments';
00136           $i++;
00137           if (isset($args[$i])) {
00138             $this->set("active_term",$args[$i]);
00139             $i++;
00140           } else {
00141             $this->error("You need to provide a term with the department requested.  e.g. ".$this->get("soc_uri")."/api1c/depts/20091 would request department information for Spring 2009");
00142           }
00143           break;
00144         case 'terms':
00145           $this->service = 'terms';
00146           $i++;
00147           break;
00148         case 'bio':
00149           $this->service = 'bio';
00150           $i++;
00151           if (isset($args[$i])) {
00152             $this->set("eid",$args[$i]);
00153           } else {
00154             $this->error("Must include an employee number");
00155           }
00156           break;
00157         case 'booklist':
00158           $this->service = 'booklist';
00159           $i++;
00160           if (isset($args[$i])) {
00161             $this->set('section',$args[$i]);
00162             $i++;
00163           } else {
00164             $this->error("Must include a section number for the book list e.g. /api1c/booklist/21012/20093 would be a book list for section 21012 in Fall 2009");
00165           }
00166           if (isset($args[$i])) {
00167             $this->set("active_term",$args[$i]);
00168             $i++;
00169           } else {
00170             $this->error("Must include a term number for the book list e.g. /api1c/booklist/21012/20093 would be a book list for section 21012 in Fall 2009");
00171           }
00172           break;
00173         case 'help':
00174         default:
00175           $this->content = $this->help();
00176           $i++;
00177           break;
00178       }
00179     }
00180     unset($args);
00181     if ($this->errorCount() == 0) {
00182       return true;
00183     }
00184     return false;
00185   }
00186   
00193   function getSession ($session, $term) {
00194     $soap = new AIS_SOAP_WS($this);
00195     $xml = $soap->xmlFromSoap("GetSessionInfo", $term, $session);
00196     if ($soap->errorCount()) {
00197       $this->error("Can't get session data from AIS SOAP Service.\n" . $soap->errors());
00198       return false;
00199     }
00200 
00201     if ($xml !== false) {
00202       // Parse for course info
00203       try {
00204         $dom = new SimpleXMLElement($xml);
00205         $json = json_encode($dom);
00206       } catch (Exception $e) {
00207         $this->error("SimpleXMLElement can't parse active sessions for $session, $term [$xml] ".$e->getMessage()."\n".$soap->errors());
00208         unset($soap);
00209         return false;
00210       }
00211       unset($dom);
00212       unset($soap);
00213       $this->cache->setCache("/session/$session/$term", $json);
00214       return true;
00215     }
00216     $this->error ("Can't find information for session $session in term $term");
00217     unset($soap);
00218     return false;
00219   }
00220 
00226   public function getCacheForTerm($term) {
00227     if (trim($term) === '') {
00228       $this->error("Need to set term for Cache");
00229       return false;
00230     }
00231     $sql = "SELECT uri FROM soc_cache WHERE uri LIKE '%$term' AND uri NOT LIKE '/booklist%' AND uri NOT LIKE '/classes%' ORDER BY soc_cache.modified ASC";
00232     $url_list = array();
00233     $this->cache->execute($sql);
00234     while ($row = $this->cache->getRow()) {
00235       if (isset($row['uri'])) {
00236         $url_list[] = $row['uri'];
00237       }
00238     }
00239     $this->cache->release();
00240     if ($this->cache->errorCount() === 0) {
00241       return $url_list;
00242     }
00243     $this->error("Can't find data for $term.");
00244     return false;
00245   }
00246 
00254   public function getBooklist($section, $term) {
00255     if ($this->get("booklist_url") === false) {
00256       $this->error("Book list URL not configured");
00257       return false;
00258     }
00259     $uri = $this->get("booklist_url");
00260     $booklist = substr($term,2).'-'.$section;
00261     // Get URL where Booklist source is stored
00262     $json = false;
00263     if (trim($uri) !== '') {
00264       if (strpos($uri,'file://') === 0) {
00265         // FIXME: when we move to PHP 5 on www.usc.edu I can replace
00266         // this with a try/catch for getting file contents.
00267         $json = @file_get_contents(substr($uri,7) . '/'. $booklist . '.json');
00268       } else {
00269         $uri = $uri.'/'.$booklist.'.json';
00270         // create curl resource
00271         $ch = curl_init();
00272 
00273   // Set up some identification for process.
00274   curl_setopt($ch, CURLOPT_USERAGENT, "soc-api1c");
00275   curl_setopt($ch, CURLOPT_REFERER, "http://web-app.usc.edu/ws/soc/models/api1c.php");
00276 
00277         // set url
00278         curl_setopt($ch, CURLOPT_URL, $uri);
00279         //return the transfer as a string
00280         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
00281 
00282         // $output contains the output string
00283         $json = curl_exec($ch);
00284         // close curl resource to free up system resources
00285         curl_close($ch);
00286         // Check to make sure we don't have an error in the output from the CURL call
00287       }
00288     }
00289     
00290     if ($json !== false) {
00291       if (strpos($json, "<!DOC") !== false || strpos($json,"404 Not Found") !==
00292  false) {
00293         $this->error($booklist . " not available.");
00294         return false;
00295       }
00296       // Check to make sure we have valid JSON
00297       $test = json_decode($json, true);
00298       if (function_exists('json_last_error')) {
00299         switch(json_last_error()) {
00300         case JSON_ERROR_DEPTH:
00301           $this->error($booklist . ' maximum stack depth exceeded.');
00302           return false;
00303         case JSON_ERROR_CTRL_CHAR:
00304           $this->error($booklist . ' unexpected control character found.');
00305           return false;
00306         case JSON_ERROR_SYNTAX:
00307           $this->error($booklist . ' syntax error, malformed JSON.');
00308           return false;
00309         }
00310       } else if (is_array($test) === false) {
00311         $this->error($booklist . " was improperly formatted." . print_r($test, 
00312 true));
00313         return false;
00314       }
00315       unset($test);
00316       $this->cache->setCache('/booklist/'.$section.'/'.$term,$json);
00317       return $json;
00318     }      
00319     $this->error("Booklist $booklist requested was an empty string.");
00320     return false;
00321   }
00322 
00328   public function getBioUrl($id) {
00329     $obj = new AIS_SOAP_WS($this);    
00330     $xml = $obj->xmlFromSoap("GetBioLink",NULL,$id);
00331     if ($obj->errorCount() == 0  && trim($xml) !== '<BioURL />' && $xml !== false && trim($xml) != "") {
00332       libxml_use_internal_errors(true);
00333       $sxml = simplexml_load_string($xml);
00334       if (! $sxml) {
00335         $this->error("XML parse error(s). GetBioLink(". strlen($xml) . "): [<pre>". $xml . "</pre>]");
00336         $xmlerrors = libxml_get_errors();
00337         foreach ($xmlerrors as $xerror) {
00338           $msg = 'ERROR line: ' . $xml[$xerror->line - 1] . " ";
00339           $msg .= str_repeat('-', $xerror->column) . ": ";  
00340           $msg .= $xerror->message;
00341           $this->error($msg);
00342         }
00343         libxml_clear_errors();
00344         return false;
00345       }
00346       $bio_link = urldecode($sxml."");
00347       unset($sxml);
00348       unset($xml);
00349       if (trim($bio_link) != "") {
00350         return $bio_link;
00351       }
00352     }
00353     unset($obj);
00354     return false;
00355   }
00356 
00357   function getDeptInfo($abbreviation) {
00358     foreach ($this->dept_info as $info) {
00359         if (isset($info["abbreviation"]) && $info["abbreviation"] === $abbreviation) {
00360             return $info;
00361         }
00362     }
00363     return false;
00364   }
00365 
00373   function getClasses ($dept, $term) {
00374     $soap = new AIS_SOAP_WS($this);
00375     
00376     $xml = mb_convert_encoding($soap->xmlFromSoap("GetCourseList",$term, $dept), 'UTF-8');
00377     
00378     if ($xml == false || $soap->errorCount() > 0) {
00379       $this->error("Can't get Course Lists from AIS SOAP Service. for $dept, $term\n".$soap->errors());
00380       unset($soap);
00381       return false;
00382     }
00383     unset($soap);
00384     $uri = "/classes/$dept/$term";
00385 
00386 
00387     // Parse for course info
00388     libxml_use_internal_errors(true);
00389     $sxml = simplexml_load_string($xml);
00390     if (! $sxml) {
00391       $this->error("XML parse error(s). GetCourseList: [".$xml."]");
00392       $xmlerrors = libxml_get_errors();
00393       foreach ($xmlerrors as $xerror) {
00394         $msg = 'line: ' . $xml[$xerror->line - 1] . " ";
00395         $msg .= str_repeat('-', $xerror->column) . ": ";
00396         $msg .= $xerror->message;
00397         $this->error($msg);
00398       }
00399       libxml_clear_errors();
00400       return false;
00401     }
00402 
00403      
00404     // Cache XML version
00405     if ($sxml !== false) {
00406         // Get Dept Info from Dept_Info field
00407         // FIXME: hook in SOC_DeptUrls Object;
00408         $DeptInfo = false;
00409         if (isset($sxml->Dept_Info)) {
00410             $info = $this->getDeptInfo(trim($sxml->Dept_Info->abbreviation));
00411             if (isset($info['uri'])) {
00412                 $sxml->Dept_Info->dept_url = $info['uri'];
00413                 $DeptInfo = $sxml->Dept_Info;
00414             }
00415         }
00416       $HasDistanceLearning = 'N';
00417 
00418       for($i = 0; $i < count($sxml->OfferedCourses->course); $i++ ) {
00419         for($j = 0; $j <  count($sxml->OfferedCourses->course[$i]->ConcurrentCourse); $j++) {
00420           for ($k = 0; $k < count($sxml->OfferedCourses->course[$i]->ConcurrentCourse[$j]->CourseData->SectionData); $k++ ) {
00421             
00422             // Create a flag for Internet based classes
00423             if (isset($sxml->OfferedCourses->course[$i]->ConcurrentCourse[$j]->CourseData->SectionData[$k]->comment) && trim($sxml->OfferedCourses->course[$i]->ConcurrentCourse[$j]->CourseData->SectionData[$k]->comment) != '') {
00424               $sxml->OfferedCourses->course[$i]->ConcurrentCourse[$j]->CourseData->SectionData[$k]->IsDistanceLearning = 'Y';
00425               $HasDistanceLearning = 'Y';
00426             } else {
00427               $sxml->OfferedCourses->course[$i]->ConcurrentCourse[$j]->CourseData->SectionData[$k]->IsDistanceLearning = 'N';
00428             }
00429 
00430             for ($l = 0; $l < count($sxml->OfferedCourses->course[$i]->ConcurrentCourse[$j]->CourseData->SectionData[$k]->instructor);$l++) {
00431         $bio_url = false;
00432               // $sxml->OfferedCourses->course[$i]->ConcurrentCourse[$j]->CourseData->SectionData[$k]->instructor[$l]
00433               if (isset($sxml->OfferedCourses->course[$i]->ConcurrentCourse[$j]->CourseData->SectionData[$k]->instructor[$l]->id)) {
00434                 $uscemployeeid = 
00435       $sxml->OfferedCourses->course[$i]->ConcurrentCourse[$j]->CourseData->SectionData[$k]->instructor[$l]->id; 
00436                 $bio_url = $this->getBioUrl($uscemployeeid);
00437               }
00438               if ($bio_url !== false) {
00439                 $sxml->OfferedCourses->course[$i]->ConcurrentCourse[$j]->CourseData->SectionData[$k]->instructor[$l]->bio_url = 
00440       trim($bio_url);
00441               } else {
00442     unset($sxml->OfferedCourses->course[$i]->ConcurrentCourse[$j]->CourseData->SectionData[$k]->instructor[$l]->bio_url);
00443               }
00444               unset($sxml->OfferedCourses->course[$i]->ConcurrentCourse[$j]->CourseData->SectionData[$k]->instructor[$l]->id);
00445             }// End of Instructors loop
00446           } // End loop of Concurrent Course Sections
00447         } // End loop Concurrent Courses
00448   
00449         $HasDistanceLearning = 'N';
00450 
00451   
00452         for ($j = 0; $j < count($sxml->OfferedCourses->course[$i]->CourseData->SectionData); $j++ ) {
00453 
00454           // Create a flag for Internet based classes
00455           if (isset($sxml->OfferedCourses->course[$i]->CourseData->SectionData[$j]->comment) && trim($sxml->OfferedCourses->course[$i]->CourseData->SectionData[$j]->comment) != '') {
00456             $sxml->OfferedCourses->course[$i]->CourseData->SectionData[$j]->IsDistanceLearning = 'Y';
00457             $HasDistanceLearning = 'Y';
00458           } else {
00459             $sxml->OfferedCourses->course[$i]->CourseData->SectionData[$j]->IsDistanceLearning = 'N';
00460           }
00461 
00462           for ($k = 0; $k < count($sxml->OfferedCourses->course[$i]->CourseData->SectionData[$j]->instructor); $k++) {
00463             $uscemployeeid = $sxml->OfferedCourses->course[$i]->CourseData->SectionData[$j]->instructor[$k]->id;
00464             
00465             $bio_url = $this->getBioUrl($uscemployeeid);
00466             if ($bio_url !== false) {
00467               $sxml->OfferedCourses->course[$i]->CourseData->SectionData[$j]->instructor[$k]->bio_url = trim($bio_url);
00468             } else {
00469               unset($sxml->OfferedCourses->course[$i]->CourseData->SectionData[$j]->instructor[$k]->bio_url);
00470             }
00471             unset($sxml->OfferedCourses->course[$i]->CourseData->SectionData[$j]->instructor[$k]->id);
00472           }// End of loop through instructors
00473         } // End of Section Loop of CourseData
00474       } // End of Course Loop
00475 
00476       // Write out sanitized CourseListResults from AIS Service.
00477       try {
00478         $json_text = json_encode($sxml);
00479       } catch (Exception $e) {
00480         $this->error($e->getMessage()." Caching $uri: [$json_text]");
00481       }
00482       if ($this->errorCount() > 0) {
00483         return false;
00484       }
00485       $this->cache->setCache(strtolower($uri), $json_text);
00486       unset($sxml);
00487       unset($xml);
00488       unset($json_text);
00489       return true;
00490     }
00491     $this->error ("Can't find classes for $dept in term $term; xml [$xml]");
00492     return false;
00493   }
00494 
00500   function getDepartments ($term) {
00501     $soap = new AIS_SOAP_WS($this);                
00502     $xml = $soap->xmlFromSoap("GetDeptList", $term, NULL);
00503     if ($soap->errorCount()) {
00504       $this->error("Can't get Dept. Lists from AIS SOAP Service.\n".$soap->errors() . " xml:[<pre>$xml</pre>]");
00505       unset($soap);
00506       return false;
00507     }
00508     unset($soap);
00509     $uri = "/departments/$term";
00510 
00511     if ($xml !== false) {
00512       // Parse for department codes
00513       try {
00514         //Ampersand hack because SIS Doesn't know how to validate their generated XML.
00515         $sxml = new SimpleXMLElement(str_replace(" & ", " &amp; ", $xml));
00516         $json = json_encode($sxml);
00517         $this->cache->setCache(strtolower($uri), $json);
00518         unset($sxml);
00519         unset($xml);
00520         return true;
00521       } catch (Exception $e) {
00522         $this->error("SimpleXMLElement can't parse active depts for $term [$xml] ".$e->getMessage()."\n");
00523       }
00524     }
00525     return false;
00526   }
00527 
00532   function getTerms () {
00533     // Try to populate the cache
00534     $soap = new AIS_SOAP_WS($this);                
00535     $xml = $soap->xmlFromSoap("GetSOCTerms",NULL,NULL);
00536     if ($soap->errorCount()) {
00537       $this->error("Can't get Term List from AIS SOAP Service.\n".$soap->errors());
00538       unset($soap);
00539       return false;
00540     }
00541     if ($xml !== false) {
00542       // Parse of terms
00543       $dom = new SimpleXMLElement($xml);
00544       $json = json_encode($dom);
00545       $this->cache->setCache(strtolower("/terms"), $json);
00546       unset($dom);
00547       unset($xml);
00548       return true;
00549     } 
00550     $this->error("Can't populate $rest_args");
00551     return false;
00552   }
00553     
00564   function eventLoop($get,$post,$session,$server,$file) {
00565     if (isset($server['PATH_INFO'])) {
00566       $this->_restParse($server['PATH_INFO']);
00567     } else {
00568       $rest_args = "/help";
00569       $this->_restParse("/help");
00570     }
00571 
00572     switch($this->service) {
00573       case 'session':
00574         $term = $this->get("active_term");
00575         $session = $this->get("active_session");
00576     
00577         $uri = "/session/".$session."/".$term;
00578         if ($this->get("cache_replace")) {
00579           $this->getSession($session, $term);
00580         }
00581         $this->content = $this->cache->getCache(strtolower($uri));
00582         if ($this->content === false) {
00583           // getSessions sets the cache as a side effect
00584           $this->getSession($session, $term);
00585           $this->content = $this->cache->getCache(strtolower($uri));
00586           if ($this->content === false) {
00587             $this->content = $this->errors();
00588           }
00589         }
00590         break;
00591       case 'classes':
00592         $term = $this->get("active_term");
00593         $dept = $this->get("active_dept");
00594     
00595         $uri = "/classes/".$dept."/".$term;
00596         if ($this->get("cache_replace")) {
00597           $this->getClasses($dept, $term);
00598         }
00599         $this->content = $this->cache->getCache($uri);
00600         if ($this->content === false) {
00601           // getClasses sets a bunch of cache records as a side effect
00602           $this->getClasses($dept, $term);
00603           $this->content = $this->cache->getCache($uri);
00604           if ($this->content === false) {
00605             $this->content = $this->errors("ERROR: can't read cache for " . $dept . ' ' . $term);
00606           }
00607         }
00608         break;
00609       case 'departments':
00610         $term = $this->get("active_term");
00611     
00612         $uri = "/departments/".$term;
00613         if ($this->get("cache_replace")) {
00614           $this->getDepartments($term);
00615         }
00616         $this->content = $this->cache->getCache($uri);
00617         if ($this->content === false) {
00618           $this->getDepartments($term);
00619           $this->content = $this->cache->getCache($uri);
00620           if ($this->content === false) {
00621             $this->content = $this->errors();
00622           }
00623         }
00624         break;
00625       case 'terms':
00626         $uri = "/terms";
00627         if ($this->get("cache_replace")) {
00628           $this->getTerms();
00629         }
00630         $this->content = $this->cache->getCache($uri);
00631         if ($this->content === false) {
00632           $this->getTerms();
00633           $this->content = $this->cache->getCache($uri);
00634           if ($this->content === false) {
00635             $this->content = $this->errors();
00636           }
00637         }
00638         break;
00639       case 'bio':
00640         $eid = $this->get("eid");
00641         $uri = "/bio/".$this->get("eid");
00642         if ($this->get("cache_replace")) {
00643 
00644           $bio_url = $this->getBioUrl($eid);
00645           $bio_url !== false ? $this->cache->setCache(strtolower($uri), $bio_url) : $this->error("Can't find Bio URL");
00646         }
00647         $this->content = $this->cache->getCache($uri);
00648         if ($this->content === false) {
00649           $bio_url = $this->getBioUrl($eid);
00650           $bio_url !== false ? $this->cache->setCache(strtolower($uri), $bio_url) : $this->error("Can't find Bio URL");
00651           if ($this->errorCount() == 0) {
00652             $this->content = $this->cache->getCache(strtolower($uri));
00653           } else {
00654             $this->content = $this->errors();
00655           }
00656         }
00657         break;
00658       case "booklist":
00659         $section = $this->get("section");
00660         $term = $this->get('active_term');
00661         $uri = "/booklist/".$section.'/'.$term;
00662         if ($this->get("cache_replace")) {
00663           $booklist_content = $this->getBooklist($section, $term);
00664           $booklist_content !== false ? $this->cache->setCache(strtolower($uri), $booklist_content) : '';
00665         }
00666         $this->content = $this->cache->getCache($uri);
00667         if ($this->content === false) {
00668           $booklist_content = $this->getBooklist($section, $term);
00669           $booklist_content !== false ? $this->cache->setCache(strtolower($uri), $booklist_content) : '';
00670           if ($this->errorCount() == 0) {
00671             $this->content = $this->cache->getCache(strtolower($uri));
00672           } else {
00673             $this->content = $this->errors();
00674           }
00675         }        
00676         break;
00677       case "";
00678       case 'help':
00679         break;
00680       default:
00681         $this->error ("'".$this->service."' not supported.");
00682         break;
00683     }
00684     if ($this->errorCount() == 0) {
00685       return true;
00686     }
00687     return false;
00688   }
00689 
00694   function contentType() {
00695     if (isset($this->content_type)) {
00696       return "Content-Type: ".$this->content_type;
00697     }
00698     return "Content-Type: text/plain";
00699   }
00700   
00706   function render() {
00707     if (isset($this->content)) {
00708       return $this->content;
00709     }
00710     return false;
00711   }
00712   
00717   function help() {
00718      $soc_uri = SOC_Widget::get('soc_uri');
00719      $content=<<<EOF
00720 <h1>USC - ITS Web services</h1>
00721 <h2>Schedule of Classes Web Services API</h2>
00722 <p />
00723 <h3>Developer</h3>
00724 <ul>
00725   <li><a href='$soc_uri/help/README.txt'>README</a> (includes example URI)</li>
00726   <li><a href='$soc_uri/docs/html'>Source Code Documentation</a></li>
00727 </ul>
00728 
00729 <p />
00730 
00731 <h3>Installation and Analysis</h3>
00732 <ul>
00733 EOF;
00734 
00735     $txt_files = glob(SOC_Widget::get('soc_path')."/*.txt");
00736     foreach ($txt_files as $filename) {
00737       if (strpos($filename,"README.txt") === false && strpos($filename,"Participants.txt") === false && strpos($filename,"INSTALLATION.txt") === false) {
00738         $link = str_replace(array($this->attributes['soc_path']."/"),
00739                           array($this->attributes['soc_uri']."/help/"), $filename);
00740         $label = str_replace(array($this->attributes['soc_path']."/",".txt","_"),array("",""," "),$filename);
00741         $content .= "\t<li><a href='$link'>$label</a></li>\n";
00742       }
00743     }
00744     $content .=<<<EOF
00745 </ul>
00746 
00747 <h3>AIS/REG source data</h3>
00748 <ul>
00749   <li><a href='http://cmsdev-jhh102.usc.edu/soc-ws/soc-ws.asmx'>REG/SOC SOAP service documentation</a></li>
00750 </ul>
00751 
00752 EOF;
00753     return $content;
00754   }
00755 }
00756 ?>