5 # Part of the ScoutLib application support library 6 # Copyright 2009-2016 Edward Almasy and Internet Scout Research Group 7 # http://scout.wisc.edu 13 # ---- PUBLIC INTERFACE -------------------------------------------------- 25 $RepDescr, &$ItemFactory, $SetsSupported = FALSE, $OaisqSupported = FALSE)
27 # save repository description 28 $this->RepDescr = $RepDescr;
30 # save supported option settings 31 $this->SetsSupported = $SetsSupported;
32 $this->OaisqSupported = $OaisqSupported;
34 # normalize repository description values 35 $this->RepDescr[
"IDPrefix"] =
36 preg_replace(
"/[^0-9a-z]/i",
"", $this->RepDescr[
"IDPrefix"]);
41 # load OAI request type and arguments 42 $this->LoadArguments();
44 # set default indent size 45 $this->IndentSize = 4;
47 # start with empty list of formats 48 $this->FormatDescrs = array();
63 public function AddFormat($Name, $TagName, $SchemaNamespace, $SchemaDefinition,
64 $SchemaVersion, $NamespaceList, $ElementList, $QualifierList,
67 # find highest current format ID 69 foreach ($this->FormatDescrs as $FormatName => $FormatDescr)
71 if ($FormatDescr[
"FormatId"] > $HighestFormatId)
73 $HighestFormatId = $FormatDescr[
"FormatId"];
77 # set new format ID to next value 78 $this->FormatDescrs[$Name][
"FormatId"] = $HighestFormatId + 1;
81 $this->FormatDescrs[$Name][
"TagName"] = $TagName;
82 $this->FormatDescrs[$Name][
"SchemaNamespace"] = $SchemaNamespace;
83 $this->FormatDescrs[$Name][
"SchemaDefinition"] = $SchemaDefinition;
84 $this->FormatDescrs[$Name][
"SchemaVersion"] = $SchemaVersion;
85 $this->FormatDescrs[$Name][
"ElementList"] = $ElementList;
86 $this->FormatDescrs[$Name][
"QualifierList"] = $QualifierList;
87 $this->FormatDescrs[$Name][
"NamespaceList"] = $NamespaceList;
88 $this->FormatDescrs[$Name][
"DefaultMap"] = $DefaultMap;
90 # start out with empty mappings list 91 if (!isset($this->FieldMappings[$Name]))
93 $this->FieldMappings[$Name] = array();
104 foreach ($this->FormatDescrs as $FormatName => $FormatDescr)
106 $FList[$FormatDescr[
"FormatId"]] = $FormatName;
118 return $this->FormatDescrs[$FormatName][
"ElementList"];
129 return $this->FormatDescrs[$FormatName][
"QualifierList"];
140 # return stored value 141 if (isset($this->FieldMappings[$FormatName][$LocalFieldName]))
143 return $this->FieldMappings[$FormatName][$LocalFieldName];
159 $this->FieldMappings[$FormatName][$LocalFieldName][]= $OAIFieldName;
170 # return stored value 171 if (isset($this->QualifierMappings[$FormatName][$LocalQualifierName]))
173 return $this->QualifierMappings[$FormatName][$LocalQualifierName];
188 $FormatName, $LocalQualifierName, $OAIQualifierName)
190 $this->QualifierMappings[$FormatName][$LocalQualifierName] =
200 # call appropriate method based on request type 201 switch (strtoupper($this->Args[
"verb"]))
204 $Response = $this->ProcessIdentify();
208 $Response = $this->ProcessGetRecord();
211 case "LISTIDENTIFIERS":
212 $Response = $this->ProcessListRecords(FALSE);
216 $Response = $this->ProcessListRecords(TRUE);
219 case "LISTMETADATAFORMATS":
220 $Response = $this->ProcessListMetadataFormats();
224 $Response = $this->ProcessListSets();
228 # return "bad argument" response 229 $Response = $this->GetResponseBeginTags();
230 $Response .= $this->GetRequestTag();
231 $Response .= $this->GetErrorTag(
232 "badVerb",
"Bad or unknown request type.");
233 $Response .= $this->GetResponseEndTags();
237 # return generated response to caller 242 # ---- PRIVATE INTERFACE ------------------------------------------------- 246 private $ItemFactory;
247 private $FormatDescrs;
248 private $FormatFields;
249 private $FieldMappings;
250 private $QualifierMappings;
252 private $SetsSupported;
253 private $OaisqSupported;
256 # ---- response generation methods 262 private function ProcessIdentify()
264 # initialize response 265 $Response = $this->GetResponseBeginTags();
267 # add request info tag 268 $Response .= $this->GetRequestTag(
"Identify");
270 # open response type tag 271 $Response .= $this->FormatTag(
"Identify");
273 # add repository info tags 274 $Response .= $this->FormatTag(
"repositoryName", $this->RepDescr[
"Name"]);
275 $Response .= $this->FormatTag(
"baseURL", $this->RepDescr[
"BaseURL"]);
276 $Response .= $this->FormatTag(
"protocolVersion",
"2.0");
277 foreach ($this->RepDescr[
"AdminEmail"] as $AdminEmail)
279 $Response .= $this->FormatTag(
"adminEmail", $AdminEmail);
281 $Response .= $this->FormatTag(
282 "earliestDatestamp", $this->RepDescr[
"EarliestDate"]);
283 $Response .= $this->FormatTag(
284 "deletedRecord",
"no");
285 $Response .= $this->FormatTag(
287 (strtoupper($this->RepDescr[
"DateGranularity"]) ==
"DATETIME")
288 ?
"YYYY-MM-DDThh:mm:ssZ" :
"YYYY-MM-DD");
290 # add repository description section 291 $Response .= $this->FormatTag(
"description");
293 "xmlns" =>
"http://www.openarchives.org/OAI/2.0/oai-identifier",
294 "xmlns:xsi" =>
"http://www.w3.org/2001/XMLSchema-instance",
295 "xsi:schemaLocation" =>
296 "http://www.openarchives.org/OAI/2.0/oai-identifier " 297 .
"http://www.openarchives.org/OAI/2.0/oai-identifier.xsd",
299 $Response .= $this->FormatTag(
300 "oai-identifier", NULL, $Attribs);
301 $Response .= $this->FormatTag(
303 $Response .= $this->FormatTag(
304 "repositoryIdentifier", $this->RepDescr[
"IDDomain"]);
305 $Response .= $this->FormatTag(
307 $Response .= $this->FormatTag(
308 "sampleIdentifier", $this->EncodeIdentifier(
"12345"));
309 $Response .= $this->FormatTag();
310 $Response .= $this->FormatTag();
312 # close response type tag 313 $Response .= $this->FormatTag();
316 $Response .= $this->GetResponseEndTags();
318 # return response to caller 326 private function ProcessGetRecord()
328 # initialize response 329 $Response = $this->GetResponseBeginTags();
331 # if arguments were bad 332 if (isset($this->Args[
"identifier"]))
334 $ItemId = $this->DecodeIdentifier($this->Args[
"identifier"]);
340 if (isset($this->Args[
"metadataPrefix"]))
342 $MetadataFormat = $this->Args[
"metadataPrefix"];
346 $MetadataFormat = NULL;
348 if (($ItemId == NULL) || ($MetadataFormat == NULL) ||
349 !is_array($this->FieldMappings[$MetadataFormat]))
351 # add request info tag with no attributes 352 $Response .= $this->GetRequestTag(
"GetRecord");
355 $Response .= $this->GetErrorTag(
"badArgument",
"Bad argument found.");
359 # add request info tag 360 $ReqArgList = array(
"identifier",
"metadataPrefix");
361 $Response .= $this->GetRequestTag(
"GetRecord", $ReqArgList);
363 # attempt to load item corresponding to record 370 $Response .= $this->GetErrorTag(
371 "idDoesNotExist",
"No item found for specified ID.");
375 # open response type tag 376 $Response .= $this->FormatTag(
"GetRecord");
378 # add tags for record 379 $Response .= $this->GetRecordTags($Item, $MetadataFormat);
381 # close response type tag 382 $Response .= $this->FormatTag();
387 $Response .= $this->GetResponseEndTags();
389 # return response to caller 399 private function ProcessListRecords($IncludeMetadata)
402 if ($IncludeMetadata)
404 $Request =
"ListRecords";
408 $Request =
"ListIdentifiers";
411 # initialize response 412 $Response = $this->GetResponseBeginTags();
414 # if resumption token supplied 415 if (isset($this->Args[
"resumptionToken"]))
417 # set expected argument lists 418 $ReqArgList = array(
"resumptionToken");
421 # parse into list parameters 422 $Args = $this->DecodeResumptionToken($this->Args[
"resumptionToken"]);
426 # set expected argument lists 427 $ReqArgList = array(
"metadataPrefix");
428 $OptArgList = array(
"from",
"until",
"set");
430 # get list parameters from incoming arguments 433 # set list starting point to beginning 434 $Args[
"ListStartPoint"] = 0;
437 # if resumption token was supplied and was bad 440 # add request info tag 441 $Response .= $this->GetRequestTag($Request, $ReqArgList, $OptArgList);
443 # add error tag indicating bad resumption token 444 $Response .= $this->GetErrorTag(
445 "badResumptionToken",
"Bad resumption token.");
447 # if other parameter also supplied 448 if (count($this->Args) > 2)
450 # add error tag indicating exclusive argument error 451 $Response .= $this->GetErrorTag(
452 "badArgument",
"Resumption token is exclusive argument.");
455 # else if resumption token supplied and other arguments also supplied 456 elseif (isset($this->Args[
"resumptionToken"]) && (count($this->Args) > 2))
458 # add error tag indicating exclusive argument error 459 $Response .= $this->GetRequestTag();
460 $Response .= $this->GetErrorTag(
461 "badArgument",
"Resumption token is exclusive argument.");
463 # else if metadata format was not specified 464 elseif (empty($Args[
"metadataPrefix"]))
466 # add request info tag with no attributes 467 $Response .= $this->GetRequestTag($Request);
469 # add error tag indicating bad argument 470 $Response .= $this->GetErrorTag(
471 "badArgument",
"No metadata format specified.");
473 # else if from or until date is specified but bad 474 elseif ((isset($Args[
"from"]) && $this->DateIsInvalid($Args[
"from"]))
475 || (isset($Args[
"until"]) && $this->DateIsInvalid($Args[
"until"])))
477 # add request info tag with no attributes 478 $Response .= $this->GetRequestTag($Request);
480 # add error tag indicating bad argument 481 $Response .= $this->GetErrorTag(
"badArgument",
"Bad date format.");
485 # add request info tag 486 $Response .= $this->GetRequestTag($Request, $ReqArgList, $OptArgList);
488 # if set requested and we do not support sets 489 if (isset($Args[
"set"]) && ($this->SetsSupported != TRUE))
491 # add error tag indicating that we don't support sets 492 $Response .= $this->GetErrorTag(
494 "This repository does not support sets.");
496 # else if requested metadata format is not supported 497 elseif (empty($this->FormatDescrs[$Args[
"metadataPrefix"]]))
499 # add error tag indicating that format is not supported 500 $Response .= $this->GetErrorTag(
501 "cannotDisseminateFormat",
502 "Metadata format \"".$Args[
"metadataPrefix"]
503 .
"\" not supported by this repository.");
508 if (isset($Args[
"set"]))
510 # if OAI-SQ supported and set represents OAI-SQ query 511 if ($this->OaisqSupported && $this->IsOaisqQuery($Args[
"set"]))
513 # parse OAI-SQ search parameters out of set name 514 $SearchParams = $this->ParseOaisqQuery(
515 $Args[
"set"], $Args[
"metadataPrefix"]);
517 # if search parameters found 518 if (count($SearchParams))
520 # perform search for items that match OAI-SQ request 523 (isset($Args[
"from"]) ? $Args[
"from"] : NULL),
524 (isset($Args[
"until"]) ? $Args[
"until"] : NULL));
534 # get list of items in set that matches incoming criteria 537 (isset($Args[
"from"]) ? $Args[
"from"] : NULL),
538 (isset($Args[
"until"]) ? $Args[
"until"] : NULL));
543 # get list of items that matches incoming criteria 545 (isset($Args[
"from"]) ? $Args[
"from"] : NULL),
546 (isset($Args[
"until"]) ? $Args[
"until"] : NULL));
550 if (count($ItemIds) == 0)
552 # add error tag indicating that no records found that match spec 553 $Response .= $this->GetErrorTag(
555 "No records were found that match the specified parameters.");
559 # open response type tag 560 $Response .= $this->FormatTag($Request);
562 # initialize count of processed items 566 foreach ($ItemIds as $ItemId)
568 # if item is within range 569 if ($ListIndex >= $Args[
"ListStartPoint"])
574 # add record for item 575 $Response .= $this->GetRecordTags(
576 $Item, $Args[
"metadataPrefix"], $IncludeMetadata);
579 # increment count of processed items 582 # stop processing if we have processed max number of items 583 $MaxItemsPerPass = 20;
584 if (($ListIndex - $Args[
"ListStartPoint"]) >= $MaxItemsPerPass)
590 # if items left unprocessed 591 if ($ListIndex < count($ItemIds))
593 # add resumption token tag 594 $Token = $this->EncodeResumptionToken(
595 (isset($Args[
"from"]) ? $Args[
"from"] : NULL),
596 (isset($Args[
"until"]) ? $Args[
"until"] : NULL),
597 (isset($Args[
"metadataPrefix"]) ?
598 $Args[
"metadataPrefix"] : NULL),
599 (isset($Args[
"set"]) ? $Args[
"set"] : NULL),
601 $Response .= $this->FormatTag(
"resumptionToken", $Token);
605 # if we started with a resumption token tag 606 if (isset($this->Args[
"resumptionToken"]))
608 # add empty resumption token tag to indicate end of set 609 $Response .= $this->FormatTag(
"resumptionToken",
"");
613 # close response type tag 614 $Response .= $this->FormatTag();
620 $Response .= $this->GetResponseEndTags();
622 # return response to caller 630 private function ProcessListMetadataFormats()
632 # initialize response 633 $Response = $this->GetResponseBeginTags();
635 # if arguments were bad 636 $Arg = isset($this->Args[
"identifier"]) ? $this->Args[
"identifier"] : NULL;
637 $ItemId = $this->DecodeIdentifier($Arg);
638 if (isset($this->Args[
"identifier"]) && ($ItemId == NULL))
641 $Response .= $this->GetRequestTag();
642 $Response .= $this->GetErrorTag(
643 "idDoesNotExist",
"Identifier unknown or illegal.");
647 # add request info tag 648 $OptArgList = array(
"identifier");
649 $Response .= $this->GetRequestTag(
"ListMetadataFormats", NULL, $OptArgList);
651 # open response type tag 652 $Response .= $this->FormatTag(
"ListMetadataFormats");
654 # for each supported format 655 foreach ($this->FormatDescrs as $FormatName => $FormatDescr)
658 $Response .= $this->FormatTag(
"metadataFormat");
660 # add tags describing format 661 $Response .= $this->FormatTag(
"metadataPrefix", $FormatName);
662 if (isset($FormatDescr[
"SchemaDefinition"]))
664 $Response .= $this->FormatTag(
"schema",
665 $FormatDescr[
"SchemaDefinition"]);
667 if (isset($FormatDescr[
"SchemaNamespace"]))
669 $Response .= $this->FormatTag(
"metadataNamespace",
670 $FormatDescr[
"SchemaNamespace"]);
674 $Response .= $this->FormatTag();
677 # close response type tag 678 $Response .= $this->FormatTag();
682 $Response .= $this->GetResponseEndTags();
684 # return response to caller 692 private function ProcessListSets()
694 # initialize response 695 $Response = $this->GetResponseBeginTags();
697 # add request info tag 698 $OptArgList = array(
"resumptionToken");
699 $Response .= $this->GetRequestTag(
"ListSets", NULL, $OptArgList);
701 # retrieve list of supported sets 702 $SetList = $this->SetsSupported ? $this->
ItemFactory->GetListOfSets() : array();
704 # if sets not supported or we have no sets 705 if ((!$this->SetsSupported) || (!count($SetList) && !$this->OaisqSupported))
707 # add error tag indicating that we do not support sets 708 $Response .= $this->GetErrorTag(
709 "noSetHierarchy",
"This repository does not support sets.");
713 # open response type tag 714 $Response .= $this->FormatTag(
"ListSets");
716 # if OAI-SQ is enabled 717 if ($this->OaisqSupported)
719 # add OAI-SQ to list of sets 720 $SetList[
"OAI-SQ"] =
"OAI-SQ";
721 $SetList[
"OAI-SQ-F"] =
"OAI-SQ-F";
724 # for each supported set 725 foreach ($SetList as $SetName => $SetSpec)
728 $Response .= $this->FormatTag(
"set");
730 # add set spec and set name 731 $Response .= $this->FormatTag(
"setSpec", $SetSpec);
732 $Response .= $this->FormatTag(
"setName", $SetName);
735 $Response .= $this->FormatTag();
738 # close response type tag 739 $Response .= $this->FormatTag();
743 $Response .= $this->GetResponseEndTags();
745 # return response to caller 750 # ---- common private methods 756 private function GetResponseBeginTags()
758 # start with XML declaration 759 $Tags =
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?".
">\n";
761 # add OAI-PMH root element begin tag 762 $Tags .=
"<OAI-PMH xmlns=\"http://www.openarchives.org/OAI/2.0/\"\n" 763 .
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" 764 .
" xsi:schemaLocation=\"http://www.openarchives.org/OAI/2.0/\n" 765 .
" http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd\">\n";
767 # add response timestamp 768 $Tags .=
" <responseDate>".date(
"Y-m-d\\TH:i:s\\Z").
"</responseDate>\n";
770 # return tags to caller 778 private function GetResponseEndTags()
780 # close out OAI-PMH root element 781 $Tags =
"</OAI-PMH>\n";
783 # return tags to caller 794 private function GetRequestTag(
795 $RequestType = NULL, $ReqArgList = NULL, $OptArgList = NULL)
797 # build attribute array 798 $AttributeList = array();
799 if ($RequestType !== NULL)
801 $AttributeList[
"verb"] = $RequestType;
803 if ($ReqArgList != NULL)
805 foreach ($ReqArgList as $ArgName)
807 if (isset($this->Args[$ArgName]))
809 $AttributeList[$ArgName] = $this->Args[$ArgName];
813 if ($OptArgList != NULL)
815 foreach ($OptArgList as $ArgName)
817 if (isset($this->Args[$ArgName]))
819 $AttributeList[$ArgName] = $this->Args[$ArgName];
824 # generate formatted tag 825 $Tag = $this->FormatTag(
"request",
826 $this->RepDescr[
"BaseURL"],
829 # return tag to caller 839 private function GetErrorTag($ErrorCode, $ErrorMessage)
841 return $this->FormatTag(
"error", $ErrorMessage, array(
"code" => $ErrorCode));
852 private function GetRecordTags($Item, $MetadataFormat, $IncludeMetadata = TRUE)
854 # if more than identifiers requested 855 if ($IncludeMetadata)
858 $Tags = $this->FormatTag(
"record");
862 # just initialize tag string with empty value 866 # add header with identifier, datestamp, and set tags 867 $Tags .= $this->FormatTag(
"header");
868 $Tags .= $this->FormatTag(
"identifier",
869 $this->EncodeIdentifier($Item->GetId()));
870 $Tags .= $this->FormatTag(
"datestamp", $Item->GetDatestamp());
871 $Sets = $Item->GetSets();
872 foreach ($Sets as $Set)
874 $Tags .= $this->FormatTag(
"setSpec", $Set);
876 $Tags .= $this->FormatTag();
878 # if more than identifiers requested 879 if ($IncludeMetadata)
882 $Tags .= $this->FormatTag(
"metadata");
884 # set up attributes for metadata format tag 885 $MFAttribs[
"xsi:schemaLocation"] =
886 $this->FormatDescrs[$MetadataFormat][
"SchemaNamespace"].
" \n" 887 .$this->FormatDescrs[$MetadataFormat][
"SchemaDefinition"];
888 $MFAttribs[
"xmlns"] = $this->FormatDescrs[$MetadataFormat][
"SchemaNamespace"];
889 if (strlen($this->FormatDescrs[$MetadataFormat][
"SchemaVersion"]) > 0)
891 $MFAttribs[
"schemaVersion"] =
892 $this->FormatDescrs[$MetadataFormat][
"SchemaVersion"];
894 $MFAttribs[
"xmlns:xsi"] =
"http://www.w3.org/2001/XMLSchema-instance";
895 foreach ($this->FormatDescrs[$MetadataFormat][
"NamespaceList"] as
896 $NamespaceName => $NamespaceURI)
898 $MFAttribs[
"xmlns:".$NamespaceName] = $NamespaceURI;
901 # open metadata format tag 902 $Tags .= $this->FormatTag($this->FormatDescrs[$MetadataFormat][
"TagName"],
905 # for each field mapping for this metadata format 906 foreach ($this->FieldMappings[$MetadataFormat] as
907 $LocalFieldName => $OAIFieldNames)
909 foreach ($OAIFieldNames as $OAIFieldName)
911 # if field looks like it has been mapped 912 if (strlen($OAIFieldName) > 0 && strlen($LocalFieldName) > 0 )
914 $Tags .= $this->FormatItemContent(
915 $Item, $MetadataFormat, $LocalFieldName, $OAIFieldName);
920 # close metadata format tag 921 $Tags .= $this->FormatTag();
924 $Tags .= $this->FormatTag();
926 # if there is additional search info about this item 927 $SearchInfo = $Item->GetSearchInfo();
928 if (count($SearchInfo))
930 # open about and search info tags 931 $Tags .= $this->FormatTag(
"about");
933 "xmlns" =>
"http://scout.wisc.edu/XML/searchInfo/",
934 "xmlns:xsi" =>
"http://www.w3.org/2001/XMLSchema-instance",
935 "xsi:schemaLocation" =>
"http://scout.wisc.edu/XML/searchInfo/ " 936 .
"http://scout.wisc.edu/XML/searchInfo.xsd",
938 $Tags .= $this->FormatTag(
"searchInfo", NULL, $Attribs);
940 # for each piece of additional info 941 foreach ($SearchInfo as $InfoName => $InfoValue)
944 $Tags .= $this->FormatTag($InfoName,
945 utf8_encode(htmlspecialchars(
946 preg_replace(
"/[\\x00-\\x1F]+/",
"", $InfoValue))));
949 # close about and search info tags 950 $Tags .= $this->FormatTag();
951 $Tags .= $this->FormatTag();
955 # if more than identifiers requested 956 if ($IncludeMetadata)
959 $Tags .= $this->FormatTag();
962 # return tags to caller 971 private function EncodeIdentifier($ItemId)
973 # return encoded value to caller 974 return "oai:".$this->RepDescr[
"IDDomain"]
975 .
":".$this->RepDescr[
"IDPrefix"].
"-".$ItemId;
984 private function DecodeIdentifier($Identifier)
986 # assume that decode will fail 989 # split ID into component pieces 990 $Pieces = explode(
":", $Identifier);
992 # if pieces look okay 993 if (($Pieces[0] ==
"oai") && ($Pieces[1] == $this->RepDescr[
"IDDomain"]))
996 $Pieces = explode(
"-", $Pieces[2]);
998 # if identifier prefix looks okay 999 if ($Pieces[0] == $this->RepDescr[
"IDPrefix"])
1001 # decoded value is final piece 1006 # return decoded value to caller 1018 private function EncodeResumptionToken(
1019 $StartingDate, $EndingDate, $MetadataFormat, $SetSpec, $ListStartPoint)
1021 # concatenate values to create token 1022 $Token = $StartingDate.
"-_-".$EndingDate.
"-_-".$MetadataFormat.
"-_-" 1023 .$SetSpec.
"-_-".$ListStartPoint;
1025 # return token to caller 1034 private function DecodeResumptionToken($ResumptionToken)
1036 # split into component pieces 1037 $Pieces = preg_split(
"/-_-/", $ResumptionToken);
1039 # if we were unable to split token 1040 if (count($Pieces) != 5)
1047 # assign component pieces to list parameters 1048 if (strlen($Pieces[0]) > 0) { $Args[
"from"] = $Pieces[0]; }
1049 if (strlen($Pieces[1]) > 0) { $Args[
"until"] = $Pieces[1]; }
1050 if (strlen($Pieces[2]) > 0) { $Args[
"metadataPrefix"] = $Pieces[2]; }
1051 if (strlen($Pieces[3]) > 0) { $Args[
"set"] = $Pieces[3]; }
1052 if (strlen($Pieces[4]) > 0) { $Args[
"ListStartPoint"] = $Pieces[4]; }
1055 # return list parameter array to caller 1064 private function DateIsInvalid($Date)
1066 # if date is null or matches required format 1067 if (empty($Date) || preg_match(
"/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $Date))
1088 private function FormatTag(
1089 $Name = NULL, $Content = NULL, $Attributes = NULL, $NewIndentLevel = NULL)
1091 static $IndentLevel = 1;
1092 static $OpenTagStack = array();
1094 # reset indent level if requested 1095 if ($NewIndentLevel !== NULL)
1097 $IndentLevel = $NewIndentLevel;
1100 # if tag name supplied 1103 # start out with appropriate indent 1104 $Tag = str_repeat(
" ", ($IndentLevel * $this->IndentSize));
1109 # if attributes supplied 1110 if ($Attributes !== NULL)
1113 foreach ($Attributes as $AttributeName => $AttributeValue)
1115 $Tag .=
" ".$AttributeName.
"=\"".$AttributeValue.
"\"";
1119 # if content supplied 1120 if ($Content !== NULL)
1126 $Tag .= htmlspecialchars($Content);
1129 $Tag .=
"</".$Name.
">\n";
1136 # increase indent level 1139 # add tag to open tag stack 1140 array_push($OpenTagStack, $Name);
1145 # decrease indent level 1146 if ($IndentLevel > 0) { $IndentLevel--; }
1148 # pop last entry off of open tag stack 1149 $LastName = array_pop($OpenTagStack);
1151 # start out with appropriate indent 1152 $Tag = str_repeat(
" ", ($IndentLevel * $this->IndentSize));
1154 # add end tag to match last open tag 1155 $Tag .=
"</".$LastName.
">\n";
1158 # return formatted tag to caller 1170 private function FormatItemContent(
1171 $Item, $MetadataFormat, $LocalFieldName, $OAIFieldName)
1173 # retrieve content for field 1174 $Content = $Item->GetValue($LocalFieldName);
1176 # retrieve qualifiers for content 1177 $Qualifier = $Item->GetQualifier($LocalFieldName);
1179 # get qualifier maps, if any exists for our format 1180 $QualifierMaps = isset($this->QualifierMappings[$MetadataFormat]) ?
1181 $this->QualifierMappings[$MetadataFormat] :
1184 # get defaults, if any exist for our format 1185 $DefaultMaps = isset($this->FormatDescrs[$MetadataFormat][
"DefaultMap"]) ?
1186 $this->FormatDescrs[$MetadataFormat][
"DefaultMap"] :
1190 # if content is array 1191 if (is_array($Content))
1193 # for each element of array 1194 foreach ($Content as $ContentIndex => $ContentValue)
1196 # if element has content 1197 if (strlen($ContentValue) > 0)
1199 # determine if we have a mapped qualifier for this item 1200 $ContentAttribs = NULL;
1201 if (isset($Qualifier[$ContentIndex]) &&
1202 strlen($Qualifier[$ContentIndex]) &&
1203 isset($QualifierMaps[$Qualifier[$ContentIndex]]) &&
1204 strlen($QualifierMaps[$Qualifier[$ContentIndex]]) )
1206 # if so, add the appropriate attribute 1207 $ContentAttribs[
"xsi:type"] =
1208 $QualifierMaps[$Qualifier[$ContentIndex]];
1211 # generate tags for this field, append them to our list 1212 $Tags .= $this->FormatTag($OAIFieldName,
1213 utf8_encode(htmlspecialchars(preg_replace(
1214 "/[\\x00-\\x1F]+/",
"", $ContentValue))),
1221 # check for a default value, fill it in if there was one 1222 if (strlen($Content)==0 && isset($DefaultMap[$OAIFieldName]))
1224 $Content = $DefaultMap[$OAIFieldName];
1227 # if field has content 1228 if (strlen($Content) > 0)
1230 # generate tag for field 1231 $ContentAttribs = NULL;
1232 if (strlen($Qualifier) > 0 &&
1233 isset($QualifierMaps[$Qualifier]) &&
1234 strlen($QualifierMaps[$Qualifier]) )
1236 $ContentAttribs[
"xsi:type"] =
1237 $QualifierMaps[$Qualifier];
1241 $Tags .= $this->FormatTag($OAIFieldName,
1242 utf8_encode(htmlspecialchars(preg_replace(
1243 "/[\\x00-\\x1F]+/",
"", $Content))),
1255 private function LoadArguments()
1257 # if request type available via POST variables 1258 if (isset($_POST[
"verb"]))
1260 # retrieve arguments from POST variables 1261 $this->Args = $_POST;
1263 # else if request type available via GET variables 1264 elseif (isset($_GET[
"verb"]))
1266 # retrieve arguments from GET variables 1267 $this->Args = $_GET;
1275 # clear out ApplicationFramework page specifier if set 1276 if (isset($this->Args[
"P"])) { unset($this->Args[
"P"]); }
1279 # ---- methods to support OAI-SQ 1286 private function IsOaisqQuery($SetString)
1288 return ((strpos($SetString,
"OAI-SQ|") === 0)
1289 || (strpos($SetString,
"OAI-SQ!") === 0)
1290 || (strpos($SetString,
"OAI-SQ-F|") === 0)
1291 || (strpos($SetString,
"OAI-SQ-F!") === 0)
1301 private function TranslateOaisqEscapes($Pieces)
1304 $N = count($Pieces);
1305 for ($Index = 0; $Index < $N; $Index++)
1307 # replace escaped chars with equivalents 1308 $Pieces[$Index] = preg_replace_callback(
1309 "/~[a-fA-F0-9]{2,2}/",
1312 'for ($Index = 0; $Index < count($Matches); $Index++)' 1314 .
' $Replacements = chr(intval(substr($Matches[$Index],1,2),16));' 1316 .
'return $Replacements;' 1321 # return translated array of pieces to caller 1332 private function ParseOaisqQuery($SetString, $FormatName)
1334 # if OAI-SQ fielded search requested 1335 if (strpos($SetString,
"OAI-SQ-F") === 0)
1337 # split set string into field names and values 1338 $Pieces = explode(substr($SetString, 8, 1), $SetString);
1340 # discard first piece (OAI-SQ designator) 1341 array_shift($Pieces);
1343 # if set string contains escaped characters 1344 if (preg_match(
"/~[a-fA-F0-9]{2,2}/", $SetString))
1346 $Pieces = $this->TranslateOaisqEscapes($Pieces);
1349 # for every two pieces 1350 $SearchParams = array();
1351 $NumPairedPieces = round(count($Pieces) / 2) * 2;
1352 for ($Index = 0; $Index < $NumPairedPieces; $Index += 2)
1354 # retrieve local field mapping 1355 foreach ($this->FieldMappings[$FormatName] as
1356 $LocalFieldName => $OAIFieldNames)
1358 if (array_search($Pieces[$Index], $OAIFieldNames) !== FALSE)
1360 $SearchParams[$LocalFieldName] = $Pieces[$Index + 1];
1367 # split set string to trim off query designator 1368 $Pieces = explode(substr($SetString, 6, 1), $SetString, 2);
1370 # if set string contains escaped characters 1371 if (preg_match(
"/~[a-fA-F0-9]{2,2}/", $SetString))
1373 $Pieces = $this->TranslateOaisqEscapes($Pieces);
1376 # remainder of set string is keyword search string 1377 $SearchParams[
"X-KEYWORD-X"] = $Pieces[1];
1380 # return array of search parameters to caller 1381 return $SearchParams;
__construct($RepDescr, &$ItemFactory, $SetsSupported=FALSE, $OaisqSupported=FALSE)
Construct an OAI server object.
FormatElementList($FormatName)
Get list of elements for a specified format.
FormatQualifierList($FormatName)
Get the list of qualifiers for a specified format.
FormatList()
Get the list of formats.
GetResponse()
Get OAI response.
GetItem($ItemId)
Retrieve item by item ID.
GetFieldMapping($FormatName, $LocalFieldName)
Get mapped name for a field.
GetQualifierMapping($FormatName, $LocalQualifierName)
Get mapping for a qualifier.
AddFormat($Name, $TagName, $SchemaNamespace, $SchemaDefinition, $SchemaVersion, $NamespaceList, $ElementList, $QualifierList, $DefaultMap)
Add a new metadata format.
SetQualifierMapping($FormatName, $LocalQualifierName, $OAIQualifierName)
Set mapping for a qualifier.
GetItems($SqlCondition=NULL)
Retrieve items.
Common factory class for item manipulation.
SetFieldMapping($FormatName, $LocalFieldName, $OAIFieldName)
Set mapping for a field.