SPTOAIServer.php
Go to the documentation of this file.
00001 <?PHP 00002 # 00003 # FILE: SPTOAIServer.php 00004 # 00005 # Copyright 2002-2010 Internet Scout 00006 # http://scout.wisc.edu 00007 # 00008 00009 class SPTOAIServer extends OAIServer { 00010 00011 # ---- PUBLIC INTERFACE -------------------------------------------------- 00012 00013 function SPTOAIServer($RetrievalSearchParameters = NULL) 00014 { 00015 global $SysConfig; 00016 00017 # grab our own database handle 00018 $this->DB = new SPTDatabase(); 00019 $DB =& $this->DB; 00020 00021 # set up repository description 00022 $DB->Query("SELECT * FROM SystemConfiguration"); 00023 $Record = $DB->FetchRow(); 00024 $RepDescr["Name"] = $SysConfig->PortalName(); 00025 $ServerName = ($_SERVER["SERVER_NAME"] != "127.0.0.1") 00026 ? $_SERVER["SERVER_NAME"] 00027 : $_SERVER["HTTP_HOST"]; 00028 $RepDescr["BaseURL"] = "http://".$ServerName.$_SERVER["SCRIPT_NAME"]; 00029 $RepDescr["DateGranularity"] = "DATE"; 00030 $RepDescr["EarliestDate"] = strlen(trim($Record["OaiEarliestDate"])) 00031 ? $Record["OaiEarliestDate"] : "1990-01-01"; 00032 $RepDescr["AdminEmail"][] = $SysConfig->AdminEmail(); 00033 $RepDescr["IDDomain"] = strlen(trim($Record["OaiIdDomain"])) 00034 ? $Record["OaiIdDomain"] : $ServerName; 00035 $RepDescr["IDPrefix"] = strlen(trim($Record["OaiIdPrefix"])) 00036 ? $Record["OaiIdPrefix"] : $ServerName; 00037 00038 # create item factory object for retrieving items from DB 00039 $this->SPTItemFactory = new SPTOAIItemFactory($RetrievalSearchParameters); 00040 00041 # call parent's constructor 00042 $this->OAIServer($DB, $RepDescr, $this->SPTItemFactory, TRUE, $SysConfig->OAISQEnabled()); 00043 00044 # set up description of nsdl_dc format 00045 $NsdldcNamespaceList = array( 00046 "nsdl_dc" => "http://ns.nsdl.org/nsdl_dc_v1.01", 00047 "dc" => "http://purl.org/dc/elements/1.1/", 00048 "dct" => "http://purl.org/dc/terms/", 00049 "ieee" => "http://www.ieee.org/xsd/LOMv1p0", 00050 ); 00051 $NsdldcElements = array( 00052 "dc:title", 00053 "dc:creator", 00054 "dc:subject", 00055 "dc:description", 00056 "dc:publisher", 00057 "dc:contributor", 00058 "dc:date", 00059 "dc:type", 00060 "dc:format", 00061 "dc:identifier", 00062 "dc:source", 00063 "dc:language", 00064 "dc:relation", 00065 "dc:coverage", 00066 "dc:rights", 00067 "dct:audience", 00068 "dct:alternative", 00069 "dct:tableOfContents", 00070 "dct:abstract", 00071 "dct:created", 00072 "dct:valid", 00073 "dct:available", 00074 "dct:issued", 00075 "dct:modified", 00076 "dct:extent", 00077 "dct:medium", 00078 "dct:isVersionOf", 00079 "dct:hasVersion", 00080 "dct:isReplacedBy", 00081 "dct:replaces", 00082 "dct:isRequiredBy", 00083 "dct:requires", 00084 "dct:isPartOf", 00085 "dct:hasPart", 00086 "dct:isReferencedBy", 00087 "dct:references", 00088 "dct:isFormatOf", 00089 "dct:hasFormat", 00090 "dct:conformsTo", 00091 "dct:spatial", 00092 "dct:temporal", 00093 "dct:mediator", 00094 "dct:dateAccepted", 00095 "dct:dateCopyrighted", 00096 "dct:dateSubmitted", 00097 "dct:educationLevel", 00098 "dct:accessRights", 00099 "dct:bibliographicCitation", 00100 "ieee:interactivityType", 00101 "ieee:interactivityLevel", 00102 "ieee:typicalLearningTime", 00103 ); 00104 $NsdldcQualifiers = array( 00105 "dct:LCSH", 00106 "dct:MESH", 00107 "dct:DDC", 00108 "dct:LCC", 00109 "dct:UDC", 00110 "dct:DCMIType", 00111 "dct:IMT", 00112 "dct:ISO639-2", 00113 "dct:RFC1766", 00114 "dct:URI", 00115 "dct:Point", 00116 "dct:ISO3166", 00117 "dct:Box", 00118 "dct:TGN", 00119 "dct:Period", 00120 "dct:W3CDTF", 00121 "dct:RFC3066", 00122 ); 00123 $this->AddFormat("nsdl_dc", "nsdl_dc:nsdl_dc", 00124 "http://ns.nsdl.org/nsdl_dc_v1.01" 00125 ." http://ns.nsdl.org/schemas/nsdl_dc/nsdl_dc_v1.01.xsd", 00126 "1.01.001", 00127 $NsdldcNamespaceList, $NsdldcElements, $NsdldcQualifiers); 00128 00129 # load field mappings from database and set in parent 00130 $Schema = new MetadataSchema(); 00131 $DB->Query("SELECT * FROM OAIFieldMappings"); 00132 while ($Record = $DB->FetchRow()) 00133 { 00134 if ($Record["OAIFieldName"] != "Unmapped") 00135 { 00136 parent::SetFieldMapping($Record["FormatName"], 00137 $Record["SPTFieldId"], 00138 $Record["OAIFieldName"]); 00139 } 00140 } 00141 00142 # load qualifier mappings from database and set in parent 00143 $DB->Query("SELECT * FROM OAIQualifierMappings"); 00144 while ($Record = $DB->FetchRow()) 00145 { 00146 if ($Record["OAIQualifierName"] != "Unmapped") 00147 { 00148 $LocalQualifier = new Qualifier($Record["SPTQualifierId"]); 00149 $LocalQualifierName = $LocalQualifier->Name(); 00150 parent::SetQualifierMapping($Record["FormatName"], 00151 $LocalQualifierName, 00152 $Record["OAIQualifierName"]); 00153 } 00154 } 00155 } 00156 00157 # add SQL conditional for selecting resources 00158 function AddSQLConditionalForResources($Conditional) 00159 { 00160 # pass conditional on to item factory 00161 $this->SPTItemFactory->AddSQLConditionalForResources($Conditional); 00162 } 00163 00164 # get/set mapping of local field to OAI field (overloads parent method) 00165 function GetFieldMapping($FormatName, $LocalFieldName) 00166 { 00167 # retrieve ID for local field 00168 $Schema = new MetadataSchema(); 00169 $LocalField = $Schema->GetFieldByName($LocalFieldName); 00170 $LocalFieldId = $LocalField->Id(); 00171 00172 # return stored value 00173 return parent::GetFieldMapping($FormatName, $LocalFieldId); 00174 } 00175 function SetFieldMapping($FormatName, $LocalFieldName, $OAIFieldName) 00176 { 00177 # retrieve ID for local field 00178 $Schema = new MetadataSchema(); 00179 $LocalField = $Schema->GetFieldByName($LocalFieldName); 00180 $LocalFieldId = $LocalField->Id(); 00181 00182 # check whether mapping is already in database 00183 $DB =& $this->DB; 00184 $MapCount = $DB->Query("SELECT COUNT(*) AS MapCount FROM OAIFieldMappings" 00185 ." WHERE FormatName = '".$FormatName."'" 00186 ." AND SPTFieldId = '".$LocalFieldId."'", 00187 "MapCount"); 00188 00189 # if mapping is already in database 00190 if ($MapCount > 0) 00191 { 00192 # change mapping in database 00193 $DB->Query("UPDATE OAIFieldMappings" 00194 ." SET OAIFieldName = '".addslashes($OAIFieldName)."'" 00195 ." WHERE FormatName = '".addslashes($FormatName)."'" 00196 ." AND SPTFieldId = '".$LocalFieldId."'"); 00197 } 00198 else 00199 { 00200 # add new mapping to database 00201 $DB->Query("INSERT INTO OAIFieldMappings" 00202 ." (FormatName, SPTFieldId, OAIFieldName) VALUES" 00203 ." ('".addslashes($FormatName)."', '".$LocalFieldId 00204 ."', '".addslashes($OAIFieldName)."')"); 00205 } 00206 00207 # call parent method 00208 parent::SetFieldMapping($FormatName, $LocalFieldId, $OAIFieldName); 00209 } 00210 00211 # set mapping of local qualifier to OAI qualifier (overloads parent method) 00212 function SetQualifierMapping($FormatName, $LocalQualifierName, $OAIQualifierName) 00213 { 00214 # retrieve ID for local qualifier 00215 $QFactory = new QualifierFactory(); 00216 $LocalQualifier = $QFactory->GetQualifierByName($LocalQualifierName); 00217 $LocalQualifierId = $LocalQualifier->Id(); 00218 00219 # check whether mapping is already in database 00220 $DB =& $this->DB; 00221 $MapCount = $DB->Query("SELECT COUNT(*) AS MapCount FROM OAIQualifierMappings" 00222 ." WHERE FormatName = '".addslashes($FormatName)."'" 00223 ." AND SPTQualifierId = '".$LocalQualifierId."'", 00224 "MapCount"); 00225 00226 # if mapping is already in database 00227 if ($MapCount > 0) 00228 { 00229 # change mapping in database 00230 $DB->Query("UPDATE OAIQualifierMappings" 00231 ." SET OAIQualifierName = '".addslashes($OAIQualifierName)."'" 00232 ." WHERE FormatName = '".addslashes($FormatName)."'" 00233 ." AND SPTQualifierId = '".$LocalQualifierId."'"); 00234 } 00235 else 00236 { 00237 # add new mapping to database 00238 $DB->Query("INSERT INTO OAIQualifierMappings" 00239 ." (FormatName, SPTQualifierId, OAIQualifierName) VALUES" 00240 ." ('".addslashes($FormatName)."', '".$LocalQualifierId 00241 ."', '".addslashes($OAIQualifierName)."')"); 00242 } 00243 00244 # call parent method 00245 parent::SetQualifierMapping($FormatName, $LocalQualifierName, $OAIQualifierName); 00246 } 00247 00248 00249 # ---- PRIVATE INTERFACE ------------------------------------------------- 00250 00251 var $DB; 00252 var $SPTItemFactory; 00253 00254 } 00255 00256 class SPTOAIItemFactory extends OAIItemFactory { 00257 00258 # ---- PUBLIC INTERFACE -------------------------------------------------- 00259 00260 # object constructor 00261 function SPTOAIItemFactory($RetrievalSearchParameters = NULL) 00262 { 00263 # save any supplied retrieval parameters 00264 $this->RetrievalSearchParameters = $RetrievalSearchParameters; 00265 } 00266 00267 function GetItem($ItemId) 00268 { 00269 # add link to full record page for item 00270 $ServerName = ($_SERVER["SERVER_NAME"] != "127.0.0.1") 00271 ? $_SERVER["SERVER_NAME"] 00272 : $_SERVER["HTTP_HOST"]; 00273 $SearchInfo["fullRecordLink"] = "http://".$ServerName.dirname($_SERVER["SCRIPT_NAME"])."/SPT--FullRecord.php?ResourceId=".$ItemId; 00274 00275 # if a search score is available for the item 00276 if (isset($this->SearchScores) && isset($this->SearchScores[$ItemId])) 00277 { 00278 # add search info for item 00279 $SearchInfo["searchScore"] = $this->SearchScores[$ItemId]; 00280 $SearchInfo["searchScoreScale"] = $this->SearchScoreScale; 00281 } 00282 00283 # attempt to create item 00284 $Item = new SPTOAIItem($ItemId, $SearchInfo); 00285 00286 # if item creation failed 00287 if ($Item->Status() == -1) 00288 { 00289 # return NULL to indicate that no item was found with that ID 00290 return NULL; 00291 } 00292 else 00293 { 00294 # return item to caller 00295 return $Item; 00296 } 00297 } 00298 00299 function GetItems($StartingDate = NULL, $EndingDate = NULL) 00300 { 00301 return $this->GetItemsInSet(NULL, $StartingDate, $EndingDate); 00302 } 00303 00304 function GetItemsInSet($Set, $StartingDate = NULL, $EndingDate = NULL) 00305 { 00306 # initialize search parameters with release flag requirement 00307 $SearchStrings["Release Flag"] = "=1"; 00308 00309 # if both begin and end date supplied 00310 if (($StartingDate != NULL) && ($EndingDate != NULL)) 00311 { 00312 # select resources created between starting and ending dates 00313 $SearchStrings["Date Of Record Creation"] = 00314 array(">=".$StartingDate, "<=".$EndingDate); 00315 } 00316 # else if begin date specified 00317 elseif ($StartingDate != NULL) 00318 { 00319 # select resources created after begin date 00320 $SearchStrings["Date Of Record Creation"] = ">=".$StartingDate; 00321 } 00322 # else if end date specified 00323 elseif ($EndingDate != NULL) 00324 { 00325 # select resources created after begin date 00326 $SearchStrings["Date Of Record Creation"] = "<=".$EndingDate; 00327 } 00328 00329 # if set specified 00330 if ($Set != NULL) 00331 { 00332 # load set mappings 00333 $this->LoadSetNameInfo(); 00334 00335 # if set is valid 00336 if (isset($this->SetFields[$Set])) 00337 { 00338 # add field spec to search strings 00339 $SearchStrings[$this->SetFields[$Set]] = "= ".$this->SetValues[$Set]; 00340 } 00341 else 00342 { 00343 # set will not match anything so return empty array to caller 00344 return array(); 00345 } 00346 } 00347 00348 # perform search for desired items 00349 $Engine = new SPTSearchEngine(); 00350 if ($this->RetrievalSearchParameters) 00351 { 00352 $SearchStrings = array_merge($SearchStrings, 00353 $this->RetrievalSearchParameters); 00354 } 00355 $SearchResults = $Engine->FieldedSearch($SearchStrings, 0, 1000000); 00356 00357 # extract resource IDs from search results 00358 $ItemIds = array_keys($SearchResults); 00359 00360 # return array of resource IDs to caller 00361 return $ItemIds; 00362 } 00363 00364 # return array containing all set specs (with human-readable set names as keys) 00365 function GetListOfSets() 00366 { 00367 # make sure set name info is loaded 00368 $this->LoadSetNameInfo(); 00369 00370 # return list of sets to caller 00371 return $this->SetSpecs; 00372 } 00373 00374 # retrieve IDs of items that match search parameters (only needed if OAI-SQ supported) 00375 function SearchForItems($SearchParams, $StartingDate = NULL, $EndingDate = NULL) 00376 { 00377 # translate field IDs into field names for search parameters 00378 $Schema = new MetadataSchema; 00379 foreach ($SearchParams as $FieldId => $Value) 00380 { 00381 if ($FieldId == "X-KEYWORD-X") 00382 { 00383 $SearchStrings["XXXKeywordXXX"] = $Value; 00384 } 00385 else 00386 { 00387 $Field = $Schema->GetField($FieldId); 00388 $SearchStrings[$Field->Name()] = $Value; 00389 } 00390 } 00391 00392 # add release flag requirement to search parameters 00393 $SearchStrings["Release Flag"] = "=1"; 00394 00395 # if both begin and end date supplied 00396 if (($StartingDate != NULL) && ($EndingDate != NULL)) 00397 { 00398 # select resources created between starting and ending dates 00399 $SearchStrings["Date Of Record Creation"] = 00400 array(">=".$StartingDate, "<=".$EndingDate); 00401 } 00402 # else if begin date specified 00403 elseif ($StartingDate != NULL) 00404 { 00405 # select resources created after begin date 00406 $SearchStrings["Date Of Record Creation"] = ">=".$StartingDate; 00407 } 00408 # else if end date specified 00409 elseif ($EndingDate != NULL) 00410 { 00411 # select resources created after begin date 00412 $SearchStrings["Date Of Record Creation"] = "<=".$EndingDate; 00413 } 00414 00415 # perform search for desired items 00416 $Engine = new SPTSearchEngine(); 00417 if ($this->RetrievalSearchParameters) 00418 { 00419 $SearchStrings = array_merge($SearchStrings, 00420 $this->RetrievalSearchParameters); 00421 } 00422 $SearchResults = $Engine->FieldedSearch($SearchStrings, 0, 1000000); 00423 00424 # save search scores 00425 $this->SearchScores = $SearchResults; 00426 $this->SearchScoreScale = $Engine->FieldedSearchWeightScale($SearchStrings); 00427 00428 # extract resource IDs from search results 00429 $ItemIds = array_keys($SearchResults); 00430 00431 # return array of resource IDs to caller 00432 return $ItemIds; 00433 } 00434 00435 00436 # ---- PRIVATE INTERFACE ------------------------------------------------- 00437 00438 var $SetSpecs; 00439 var $SetFields; 00440 var $SetValues; 00441 var $RetrievalSearchParameters; 00442 var $SearchScores; 00443 var $SearchScoreScale; 00444 00445 # normalize value for use as an OAI set spec 00446 function NormalizeForSetSpec($Name) 00447 { 00448 return preg_replace("/[^a-zA-Z0-9\-_.!~*'()]/", "", $Name); 00449 } 00450 00451 # load normalized set names and name mappings 00452 function LoadSetNameInfo() 00453 { 00454 # if set names have not already been loaded 00455 if (!isset($this->SetSpecs)) 00456 { 00457 # start with empty list of sets 00458 $this->SetSpecs = array(); 00459 $this->SetFields = array(); 00460 $this->SetValues = array(); 00461 00462 # for each metadata field that is a type that can be used for sets 00463 $Schema = new MetadataSchema(); 00464 $Fields = $Schema->GetFields(MetadataSchema::MDFTYPE_TREE|MetadataSchema::MDFTYPE_CONTROLLEDNAME|MetadataSchema::MDFTYPE_OPTION); 00465 foreach ($Fields as $Field) 00466 { 00467 # if field is flagged as being used for OAI sets 00468 if ($Field->UseForOaiSets()) 00469 { 00470 # retrieve all possible values for field 00471 $FieldValues = $Field->GetPossibleValues(); 00472 00473 # prepend field name to each value and add to list of sets 00474 $FieldName = $Field->Name(); 00475 $NormalizedFieldName = $this->NormalizeForSetSpec($FieldName); 00476 foreach ($FieldValues as $Value) 00477 { 00478 $SetSpec = $NormalizedFieldName.":" 00479 .$this->NormalizeForSetSpec($Value); 00480 $this->SetSpecs[$FieldName.": ".$Value] = $SetSpec; 00481 $this->SetFields[$SetSpec] = $FieldName; 00482 $this->SetValues[$SetSpec] = $Value; 00483 } 00484 } 00485 } 00486 } 00487 } 00488 } 00489 00490 class SPTOAIItem extends OAIItem { 00491 00492 # ---- PUBLIC INTERFACE -------------------------------------------------- 00493 00494 # object constructor 00495 function SPTOAIItem($ItemId, $SearchInfo = NULL) 00496 { 00497 # save ID for later use 00498 $this->Id = $ItemId; 00499 00500 # save any search info supplied 00501 $this->SearchInfo = $SearchInfo; 00502 00503 # attempt to create resource object 00504 $this->Resource = new Resource($ItemId); 00505 00506 # if resource object creation failed 00507 if ($this->Resource->Status() == -1) 00508 { 00509 # set status to -1 to indicate constructor failure 00510 $this->LastStatus = -1; 00511 } 00512 else 00513 { 00514 # set status to 1 to indicate constructor success 00515 $this->LastStatus = 1; 00516 00517 # if cumulative rating data is available for this resource 00518 global $SysConfig; 00519 if ($SysConfig->ResourceRatingsEnabled() 00520 && $this->Resource->CumulativeRating()) 00521 { 00522 # add cumulative rating data to search info 00523 $this->SearchInfo["cumulativeRating"] = 00524 $this->Resource->CumulativeRating(); 00525 $this->SearchInfo["cumulativeRatingScale"] = 100; 00526 } 00527 } 00528 } 00529 00530 function GetId() { return $this->Id; } 00531 00532 function GetDatestamp() 00533 { 00534 $DateString = $this->Resource->Get("Date Of Record Creation"); 00535 if ($DateString == "0000-00-00 00:00:00") { $DateString = date("Y-m-d"); } 00536 $Date = new Date($DateString); 00537 return $Date->FormattedISO8601(); 00538 } 00539 00540 function GetValue($ElementName) 00541 { 00542 # retrieve value 00543 $ReturnValue = $this->Resource->GetByFieldId($ElementName); 00544 00545 # strip out any HTML tags if text value 00546 if (is_string($ReturnValue)) 00547 { 00548 $ReturnValue = strip_tags($ReturnValue); 00549 } 00550 00551 # format correctly if standardized date 00552 if ($this->GetQualifier($ElementName) == "W3C-DTF") 00553 { 00554 $Timestamp = strtotime($ReturnValue); 00555 $ReturnValue = date('Y-m-d\TH:i:s', $Timestamp) 00556 .substr_replace(date('O', $Timestamp), ':', 3, 0); 00557 } 00558 00559 # return value to caller 00560 return $ReturnValue; 00561 } 00562 00563 function GetQualifier($ElementName) 00564 { 00565 $ReturnValue = NULL; 00566 $Qualifier = $this->Resource->GetQualifierByFieldId($ElementName, TRUE); 00567 if (is_array($Qualifier)) 00568 { 00569 foreach ($Qualifier as $ItemId => $QualObj) 00570 { 00571 if (is_object($QualObj)) 00572 { 00573 $ReturnValue[$ItemId] = $QualObj->Name(); 00574 } 00575 } 00576 } 00577 else 00578 { 00579 if (isset($Qualifier) && is_object($Qualifier)) 00580 { 00581 $ReturnValue = $Qualifier->Name(); 00582 } 00583 } 00584 return $ReturnValue; 00585 } 00586 00587 function GetSets() 00588 { 00589 # start out with empty list 00590 $Sets = array(); 00591 00592 # for each possible metadata field 00593 $Schema = new MetadataSchema(); 00594 $Fields = $Schema->GetFields(MetadataSchema::MDFTYPE_TREE|MetadataSchema::MDFTYPE_CONTROLLEDNAME|MetadataSchema::MDFTYPE_OPTION); 00595 foreach ($Fields as $Field) 00596 { 00597 # if field is flagged for use for OAI sets 00598 if ($Field->UseForOaiSets()) 00599 { 00600 # retrieve values for resource for this field and add to set list 00601 $FieldName = $Field->Name(); 00602 $Values = $this->Resource->Get($FieldName); 00603 if (isset($Values) && ($Values != NULL)) 00604 { 00605 $NormalizedFieldName = $this->NormalizeForSetSpec($FieldName); 00606 if (is_array($Values) && count($Values)) 00607 { 00608 foreach ($Values as $Value) 00609 { 00610 $Sets[] = $NormalizedFieldName.":" 00611 .$this->NormalizeForSetSpec($Value); 00612 } 00613 } 00614 else 00615 { 00616 $Sets[] = $NormalizedFieldName.":" 00617 .$this->NormalizeForSetSpec($Values); 00618 } 00619 } 00620 } 00621 } 00622 00623 # return list of sets to caller 00624 return $Sets; 00625 } 00626 00627 function GetSearchInfo() 00628 { 00629 return $this->SearchInfo; 00630 } 00631 00632 function Status() 00633 { 00634 return $this->LastStatus; 00635 } 00636 00637 00638 # ---- PRIVATE INTERFACE ------------------------------------------------- 00639 00640 var $Id; 00641 var $Resource; 00642 var $LastStatus; 00643 var $SearchInfo; 00644 00645 # normalize value for use as an OAI set spec 00646 function NormalizeForSetSpec($Name) 00647 { 00648 return preg_replace("/[^a-zA-Z0-9\-_.!~*'()]/", "", $Name); 00649 } 00650 }