3 # FILE: MetadataSchema.php 5 # Part of the Collection Workflow Integration System (CWIS) 6 # Copyright 2012-2013 Edward Almasy and Internet Scout Research Group 7 # http://scout.wisc.edu/cwis 16 # ---- PUBLIC INTERFACE -------------------------------------------------- 18 # metadata field base types 19 # (must parallel MetadataFields.FieldType declaration in install/CreateTables.sql 20 # and MetadataField::$FieldTypeDBEnums declaration below) 37 # types of field ordering 62 # names used for display and edit orders 74 public function __construct($SchemaId = self::SCHEMAID_DEFAULT)
77 $this->
Id = $SchemaId;
79 # set up item factory base class 81 "MetadataField",
"MetadataFields",
"FieldId",
"FieldName", FALSE,
82 "SchemaId = ".intval($this->
Id()));
84 # load schema info from database 85 $this->DB->Query(
"SELECT * FROM MetadataSchemas" 86 .
" WHERE SchemaId = ".intval($SchemaId));
87 if ($this->DB->NumRowsSelected() < 1)
89 throw new Exception(
"Attempt to load metadata schema with " 90 .
" invalid ID (".$SchemaId.
") at " 91 .StdLib::GetMyCaller().
".");
93 $Info = $this->DB->FetchRow();
94 $this->
Name = $Info[
"Name"];
100 if (!isset(self::$FieldMappings[$this->
Id]))
102 self::$FieldMappings[$this->Id] = array();
105 # start with field info caching enabled 106 $this->CachingOn = TRUE;
120 # retrieve all constants for class 121 $Reflect =
new ReflectionClass(get_class());
122 $Constants = $Reflect->getConstants();
125 foreach ($Constants as $CName => $CValue)
127 # if value matches and prefix (if supplied) matches 128 if (($CValue == $Value)
129 && (($Prefix === NULL) || (strpos($CName, $Prefix) === 0)))
131 # return name to caller 136 # report to caller that no matching constant was found 162 $ResourceName = NULL)
164 # supply privilege settings if none provided 165 if ($AuthorPrivs === NULL) { $AuthorPrivs =
new PrivilegeSet(); }
166 if ($EditPrivs === NULL) { $EditPrivs =
new PrivilegeSet(); }
167 if ($ViewPrivs === NULL) { $ViewPrivs =
new PrivilegeSet(); }
169 # add schema to database 171 if (strtoupper($Name) ==
"RESOURCES")
173 $Id = self::SCHEMAID_DEFAULT;
175 elseif (strtoupper($Name) ==
"USER")
177 $Id = self::SCHEMAID_USER;
181 $Id =
$DB->Query(
"SELECT SchemaId FROM MetadataSchemas" 182 .
" ORDER BY SchemaId DESC LIMIT 1",
"SchemaId") + 1;
184 $DB->Query(
"INSERT INTO MetadataSchemas" 185 .
" (SchemaId, Name, ViewPage," 186 .
" AuthoringPrivileges, EditingPrivileges, ViewingPrivileges)" 187 .
" VALUES (".intval($Id).
"," 188 .
"'".addslashes($Name).
"'," 189 .
"'".
$DB->EscapeString($ViewPage).
"'," 190 .
"'".
$DB->EscapeString($AuthorPrivs->Data()).
"'," 191 .
"'".
$DB->EscapeString($EditPrivs->Data()).
"'," 192 .
"'".
$DB->EscapeString($ViewPrivs->Data()).
"')");
194 # construct the new schema 197 # set schema name if none supplied 200 $Schema->Name(
"Metadata Schema ".$Id);
203 # set the resource name if one is supplied 204 if ($ResourceName === NULL)
208 $Schema->ResourceName($ResourceName);
210 # create display and edit orders 214 # return the new schema 224 # delete resources associated with schema 226 $ResourceIds = $RFactory->GetItemIds();
227 foreach ($ResourceIds as $ResourceId)
229 $Resource =
new Resource($ResourceId);
233 # delete fields associated with schema 234 $Fields = $this->
GetFields(NULL, NULL, TRUE, TRUE);
235 foreach ($Fields as $FieldId => $Field)
240 # delete metadata field orders associated with schema 246 # remove schema info from database 247 $this->DB->Query(
"DELETE FROM MetadataSchemas WHERE SchemaId = " 259 $DB->Query(
"SELECT * FROM MetadataSchemas" 260 .
" WHERE SchemaId = ".intval($SchemaId));
261 return (
$DB->NumRowsSelected() > 0) ? TRUE : FALSE;
271 # return value to caller 272 return intval($this->
Id);
280 public function Name($NewValue = NULL)
282 # set new name if one supplied 283 if ($NewValue !== NULL)
285 $this->DB->Query(
"UPDATE MetadataSchemas" 286 .
" SET Name = '".addslashes($NewValue).
"'" 287 .
" WHERE SchemaId = '".intval($this->
Id).
"'");
288 $this->
Name = $NewValue;
291 # get the name if it hasn't been cached yet 292 if (!isset($this->
Name))
294 $this->
Name = $this->DB->Query(
"SELECT * FROM MetadataSchemas" 295 .
" WHERE SchemaId = '".intval($this->
Id).
"'",
"Name");
298 # return current value to caller 311 # set new abbreviated name if one supplied 312 if ($NewValue !== NULL)
314 $this->DB->Query(
"UPDATE MetadataSchemas" 315 .
" SET AbbreviatedName = '".addslashes($NewValue).
"'" 316 .
" WHERE SchemaId = '".intval($this->
Id).
"'");
320 # get the abbreviated name if it hasn't been cached yet 324 "SELECT AbbreviatedName FROM MetadataSchemas" 325 .
" WHERE SchemaId = '".intval($this->
Id).
"'",
"AbbreviatedName");
328 # most schema won't have this field set 329 # fall back to the default value: the first letter of 336 # return current value to caller 337 return $this->AbbreviatedName;
347 # set new resource name if one supplied 348 if ($NewValue !== NULL)
351 UPDATE MetadataSchemas 352 SET ResourceName = '".addslashes($NewValue).
"' 353 WHERE SchemaId = '".intval($this->
Id).
"'");
357 # get the name if it hasn't been cached yet 361 SELECT * FROM MetadataSchemas 362 WHERE SchemaId = '".intval($this->
Id).
"'",
365 # use the default resource name if one isn't set 372 # return current value to caller 373 return $this->ResourceName;
383 # set new viewing page if one supplied 384 if ($NewValue !== NULL)
386 $this->DB->Query(
"UPDATE MetadataSchemas" 387 .
" SET ViewPage = '".addslashes($NewValue).
"'" 388 .
" WHERE SchemaId = '".intval($this->
Id).
"'");
392 # get the view page if it hasn't been cached yet 395 $this->
ViewPage = $this->DB->Query(
"SELECT * FROM MetadataSchemas" 396 .
" WHERE SchemaId = '".intval($this->
Id).
"'",
"ViewPage");
399 # return current value to caller 400 return $this->ViewPage;
410 # if new privileges supplied 411 if ($NewValue !== NULL)
413 # store new privileges in database 414 $this->DB->Query(
"UPDATE MetadataSchemas" 415 .
" SET AuthoringPrivileges = '" 416 .$this->DB->EscapeString($NewValue->Data()).
"'" 417 .
" WHERE SchemaId = ".intval($this->
Id));
421 # return current value to caller 422 return $this->AuthoringPrivileges;
432 # if new privileges supplied 433 if ($NewValue !== NULL)
435 # store new privileges in database 436 $this->DB->Query(
"UPDATE MetadataSchemas" 437 .
" SET EditingPrivileges = '" 438 .$this->DB->EscapeString($NewValue->Data()).
"'" 439 .
" WHERE SchemaId = ".intval($this->
Id));
443 # return current value to caller 444 return $this->EditingPrivileges;
454 # if new privileges supplied 455 if ($NewValue !== NULL)
457 # store new privileges in database 458 $this->DB->Query(
"UPDATE MetadataSchemas" 459 .
" SET ViewingPrivileges = '" 460 .$this->DB->EscapeString($NewValue->Data()).
"'" 461 .
" WHERE SchemaId = ".intval($this->
Id));
465 # return current value to caller 466 return $this->ViewingPrivileges;
478 # get authoring privilege set for schema 481 # user can author if privileges are greater than resource set 482 $CanAuthor = $AuthorPrivs->MeetsRequirements($User);
484 # allow plugins to modify result of permission check 485 $SignalResult = $GLOBALS[
"AF"]->SignalEvent(
486 "EVENT_RESOURCE_AUTHOR_PERMISSION_CHECK", array(
489 "CanAuthor" => $CanAuthor));
490 $CanAuthor = $SignalResult[
"CanAuthor"];
492 # report back to caller whether user can author field 505 # get editing privilege set for schema 508 # user can edit if privileges are greater than resource set 509 $CanEdit = $EditPrivs->MeetsRequirements($User);
511 # allow plugins to modify result of permission check 512 $SignalResult = $GLOBALS[
"AF"]->SignalEvent(
513 "EVENT_RESOURCE_EDIT_PERMISSION_CHECK", array(
516 "CanEdit" => $CanEdit,
517 "Schema" => $this, ));
518 $CanEdit = $SignalResult[
"CanEdit"];
520 # report back to caller whether user can edit field 533 # get viewing privilege set for schema 536 # user can view if privileges are greater than resource set 537 $CanView = $ViewPrivs->MeetsRequirements($User);
539 # allow plugins to modify result of permission check 540 $SignalResult = $GLOBALS[
"AF"]->SignalEvent(
541 "EVENT_RESOURCE_VIEW_PERMISSION_CHECK", array(
544 "CanView" => $CanView,
545 "Schema" => $this, ));
546 $CanView = $SignalResult[
"CanView"];
548 # report back to caller whether user can view field 559 # get the query/GET parameters for the view page 560 $Query = parse_url($this->
ViewPage(), PHP_URL_QUERY);
562 # the URL couldn't be parsed 563 if (!is_string($Query))
568 # parse the GET parameters out of the query string 569 $GetVars = ParseQueryString($Query);
571 # search for the ID parameter 572 $Result = array_search(
"\$ID", $GetVars);
574 return $Result !== FALSE ? $Result : NULL;
591 # get the query/GET parameters for the view page 592 $Query = parse_url($this->
ViewPage(), PHP_URL_QUERY);
594 # can't perform matching if the URL couldn't be parsed 595 if (!is_string($Query))
600 # parse the GET parameters out of the query string 601 $GetVars = ParseQueryString($Query);
603 # now, get the query/GET parameters from the path given 604 $PathQuery = parse_url($Path, PHP_URL_QUERY);
606 # can't perform matching if the URL couldn't be parsed 607 if (!is_string($PathQuery))
612 # parse the GET parameters out of the path's query string 613 $PathGetVars = ParseQueryString($PathQuery);
615 # make sure the given path GET parameters contain at least the GET 616 # parameters from the view page and that all non-variable parameters are 617 # equal. the path GET parameters may contain more, which is okay 618 foreach ($GetVars as $GetVarName => $GetVarValue)
620 # there's a required parameter that is not included in the path GET 622 if (!array_key_exists($GetVarName, $PathGetVars))
627 # require the path's value to be equal to the view page's value if 628 # the view page's value is not a variable, 629 if ($PathGetVars[$GetVarName] != $GetVarValue
630 && (!strlen($GetVarValue) || $GetVarValue{0} !=
"$"))
636 # the path matches the view page path 646 $this->CachingOn = $NewValue;
659 $FieldName, $FieldType, $Optional = TRUE, $DefaultValue = NULL)
661 # clear any existing error messages 662 if (array_key_exists(__METHOD__, $this->ErrorMsgs))
663 { unset($this->ErrorMsgs[__METHOD__]); }
669 $FieldName, $Optional, $DefaultValue);
671 catch (Exception $Exception)
673 $this->ErrorMsgs[__METHOD__][] = $Exception->getMessage();
677 # return new field to caller 697 # clear loading status 699 if (array_key_exists(__METHOD__, $this->ErrorMsgs))
700 { unset($this->ErrorMsgs[__METHOD__]); }
702 # check that file exists and is readable 703 if (!file_exists($FileName))
705 $this->ErrorMsgs[__METHOD__][] =
"Could not find XML file '" 709 elseif (!is_readable($FileName))
711 $this->ErrorMsgs[__METHOD__][] =
"Could not read from XML file '" 717 libxml_use_internal_errors(TRUE);
718 $XmlData = simplexml_load_file($FileName);
719 $Errors = libxml_get_errors();
720 libxml_use_internal_errors(FALSE);
723 if ($XmlData === FALSE)
725 # retrieve XML error messages 726 foreach ($Errors as $Err)
728 $ErrType = ($Err->level == LIBXML_ERR_WARNING) ?
"Warning" 729 : (($Err->level == LIBXML_ERR_WARNING) ?
"Error" 731 $this->ErrorMsgs[__METHOD__][] =
"XML ".$ErrType.
": ".$Err->message
732 .
" (".$Err->file.
":".$Err->line.
",".$Err->column.
")";
735 # else if no metadata fields found record error message 736 elseif (!count($XmlData->MetadataField))
738 $this->ErrorMsgs[__METHOD__][] =
"No metadata fields found.";
740 # else process metadata fields 743 # for each metadata field entry found 746 foreach ($XmlData->MetadataField as $FieldXml)
750 # pull out field type if present 751 if (isset($FieldXml->Type))
753 $FieldType =
"MetadataSchema::".$FieldXml->Type;
754 if (!defined($FieldType))
756 $FieldType =
"MetadataSchema::MDFTYPE_" 757 .strtoupper(preg_replace(
"/\\s+/",
"",
762 # if required values are missing 763 if (!isset($FieldXml->Name) || !isset($FieldXml->Type)
764 || !defined($FieldType))
766 # add error message about required value missing 767 if (!isset($FieldXml->Name))
769 $this->ErrorMsgs[__METHOD__][] =
770 "Field name not found (MetadataField #" 775 $this->ErrorMsgs[__METHOD__][] =
776 "Valid type not found for field '" 777 .$FieldXml->Name.
"' (MetadataField #" 781 # else if there is not already a field with this name 782 elseif (!$this->
NameIsInUse(trim($FieldXml->Name)))
785 $Field = $this->
AddField($FieldXml->Name, constant($FieldType));
787 # if field creation failed 790 # add any error message to our error list 792 foreach ($ErrorMsgs as $Msg)
794 $this->ErrorMsgs[__METHOD__][] =
800 # add field to list of created fields 803 # for other field attributes 804 foreach ($FieldXml as $MethodName => $Value)
806 # if tags look valid and have not already been set 807 if (method_exists($Field, $MethodName)
808 && ($MethodName !=
"Name")
809 && ($MethodName !=
"Type"))
811 # if tag indicates privilege set 812 if (preg_match(
"/^[a-z]+Privileges\$/i",
815 # save element for later processing 816 $PrivilegesToSet[$Field->Id()][$MethodName] = $Value;
820 # condense down any extraneous whitespace 821 $Value = preg_replace(
"/\s+/",
" ", trim($Value));
823 # set value for field 824 $Field->$MethodName($Value);
829 # save the temp ID so that any privileges to set 830 # can be mapped to the actual ID when the field is 832 $TempId = $Field->Id();
834 # make new field permanent 835 $Field->IsTempItem(FALSE);
837 # map privileges to set to the permanent field ID 838 if (isset($PrivilegesToSet) &&
839 isset($PrivilegesToSet[$TempId]) )
841 # copy the privileges over 842 $PrivilegesToSet[$Field->Id()] =
843 $PrivilegesToSet[$TempId];
845 # remove the values for the temp ID 846 unset($PrivilegesToSet[$TempId]);
852 # if we have privileges to set 853 if (isset($PrivilegesToSet))
855 # for each field with privileges 856 foreach ($PrivilegesToSet as $FieldId => $Privileges)
858 # load the field for which to set the privileges 861 # for each set of privileges for field 862 foreach ($Privileges as $MethodName => $Value)
864 # convert privilege value 865 $Value = $this->ConvertXmlToPrivilegeSet($Value);
867 # if conversion failed 870 # add resulting error messages to our list 872 "ConvertXmlToPrivilegeSet");
873 foreach ($ErrorMsgs as $Msg)
875 $this->ErrorMsgs[__METHOD__][] =
876 $Msg.
" (ConvertXmlToPrivilegeSet)";
881 # set value for field 882 $Field->$MethodName($Value);
888 # if errors were found during creation 889 if (array_key_exists(__METHOD__, $this->ErrorMsgs) || $TestRun)
891 # remove any fields that were created 900 # set owner for new fields (if supplied) 905 $Field->Owner($Owner);
911 # report success or failure based on whether errors were recorded 912 return (array_key_exists(__METHOD__, $this->ErrorMsgs)) ? FALSE : TRUE;
922 return $this->NewFields;
936 if ($Method === NULL)
938 return $this->ErrorMsgs;
942 if (!method_exists($this, $Method))
944 throw new Exception(
"Error messages requested for non-existent" 945 .
" method (".$Method.
").");
947 return array_key_exists(__CLASS__.
"::".$Method, $this->ErrorMsgs)
948 ? $this->ErrorMsgs[__CLASS__.
"::".$Method] : array();
963 # assume field addition will fail 964 $Field = self::MDFSTAT_ERROR;
966 # add XML prefixes if needed 968 if (!preg_match(
"/^<\?xml/i", $Xml))
970 if (!preg_match(
"/^<document>/i", $Xml))
972 $Xml =
"<document>".$Xml.
"</document>";
974 $Xml =
"<?xml version='1.0'?".
">".$Xml;
978 $XmlData = simplexml_load_string($Xml);
980 # if required values are present 981 if (is_object($XmlData)
982 && isset($XmlData->Name)
983 && isset($XmlData->Type)
984 && constant(
"MetadataSchema::".$XmlData->Type))
986 # create the metadata field 989 constant(
"MetadataSchema::".$XmlData->Type));
991 # if field creation succeeded 994 # for other field attributes 995 foreach ($XmlData as $MethodName => $Value)
997 # if they look valid and have not already been set 998 if (method_exists($Field, $MethodName)
999 && ($MethodName !=
"Name")
1000 && ($MethodName !=
"Type"))
1002 # if tag indicates privilege set 1003 if (preg_match(
"/^[a-z]+Privileges\$/i",
1006 # save element for later processing 1007 $PrivilegesToSet[$MethodName] = $Value;
1011 # condense down any extraneous whitespace 1012 $Value = preg_replace(
"/\s+/",
" ", trim($Value));
1014 # set value for field 1015 $Field->$MethodName($Value);
1020 # make new field permanent 1021 $Field->IsTempItem(FALSE);
1023 # if we have privileges to set 1024 if (isset($PrivilegesToSet))
1026 # for each set of privileges for field 1027 foreach ($PrivilegesToSet as $MethodName => $Value)
1029 # convert privilege value 1030 $Value = $this->ConvertXmlToPrivilegeSet($Value);
1032 # if conversion failed 1033 if ($Value === NULL)
1035 # add resulting error messages to our list 1037 "ConvertXmlToPrivilegeSet");
1038 foreach ($ErrorMsgs as $Msg)
1040 $this->ErrorMsgs[__METHOD__][] =
1041 $Msg.
" (ConvertXmlToPrivilegeSet)";
1046 # set value for field 1047 $Field->$MethodName($Value);
1054 # return new field (if any) to caller 1065 $Field = $this->
GetField($FieldId);
1066 if ($Field !== NULL)
1069 $AF->SignalEvent(
"EVENT_PRE_FIELD_DELETE",
1070 array(
"FieldId" => $Field->Id()) );
1090 # convert field name to ID if necessary 1091 if (!is_numeric($FieldId))
1093 $FieldName = $FieldId;
1095 if ($FieldId === FALSE)
1097 throw new InvalidArgumentException(
"Attempt to retrieve field" 1098 .
" with unknown name (".$FieldName.
").");
1102 # if caching is off or field is not already loaded 1103 if (($this->CachingOn != TRUE) || !isset($Fields[$FieldId]))
1110 catch (Exception $Exception)
1112 $Fields[$FieldId] = NULL;
1116 # return field to caller if it comes from our schema 1117 return ($Fields[$FieldId] !== NULL &&
1118 $this->
Id() == $Fields[$FieldId]->SchemaId()) ?
1119 $Fields[$FieldId] : NULL;
1134 return ($FieldId === FALSE) ? NULL : $this->
GetField($FieldId);
1146 return ($FieldId === NULL) ? NULL : $this->
GetField($FieldId);
1170 static $FieldIdsByLabel;
1172 # if caching is off or field ID is already loaded 1173 if (($this->CachingOn != TRUE) || !isset($FieldIdsByLabel[$FieldLabel]))
1175 # retrieve field ID from DB 1176 $Condition = $IgnoreCase
1177 ?
"WHERE LOWER(Label) = '".addslashes(strtolower($FieldLabel)).
"'" 1178 :
"WHERE Label = '".addslashes($FieldLabel).
"'";
1179 $Condition .=
" AND SchemaId = ".intval($this->
Id);
1180 $FieldIdsByLabel[$FieldLabel] = $this->DB->Query(
1181 "SELECT FieldId FROM MetadataFields ".$Condition,
"FieldId");
1184 return $FieldIdsByLabel[$FieldLabel];
1194 return is_numeric($Field)
1212 public function GetFields($FieldTypes = NULL, $OrderType = NULL,
1213 $IncludeDisabledFields = FALSE, $IncludeTempFields = FALSE)
1215 # create empty array to pass back 1218 # for each field type in database 1219 $this->DB->Query(
"SELECT FieldId, FieldType FROM MetadataFields" 1220 .
" WHERE SchemaId = ".intval($this->
Id)
1221 .(!$IncludeDisabledFields ?
" AND Enabled != 0" :
"")
1222 .(!$IncludeTempFields ?
" AND FieldId >= 0" :
""));
1223 while ($Record = $this->DB->FetchRow())
1225 # if field type is known 1228 # if no specific type requested or if field is of requested type 1229 if (($FieldTypes == NULL)
1233 # create field object and add to array to be passed back 1234 $Fields[$Record[
"FieldId"]] = $this->
GetField($Record[
"FieldId"]);
1239 # if field sorting requested 1240 if ($OrderType !== NULL)
1242 # update field comparison ordering if not set yet 1248 $this->FieldCompareType = $OrderType;
1250 # sort field array by requested order type 1251 uasort($Fields, array($this,
"CompareFieldOrder"));
1254 # return array of field objects to caller 1273 $IncludeDisabledFields = FALSE, $IncludeTempFields = FALSE)
1275 $Fields = $this->
GetFields($FieldTypes, $OrderType,
1276 $IncludeDisabledFields, $IncludeTempFields);
1278 $FieldNames = array();
1279 foreach($Fields as $Field)
1281 $FieldNames[$Field->Id()] = $Field->Name();
1306 $SelectedFieldId = NULL, $IncludeNullOption = TRUE,
1307 $AddEntries = NULL, $AllowMultiple = FALSE, $Disabled = FALSE)
1309 # retrieve requested fields 1312 # transform field names to labels 1313 foreach ($FieldNames as $FieldId => $FieldName)
1315 $FieldNames[$FieldId] = $this->
GetField($FieldId)->GetDisplayName();
1318 # add in null entry if requested 1319 if ($IncludeNullOption)
1321 $FieldNames = array(
"" =>
"--") + $FieldNames;
1324 # add additional entries if supplied 1327 $FieldNames = $FieldNames + $AddEntries;
1330 # construct option list 1331 $OptList =
new HtmlOptionList($OptionListName, $FieldNames, $SelectedFieldId);
1332 $OptList->MultipleAllowed($AllowMultiple);
1333 $OptList->Disabled($Disabled);
1335 # return option list HTML to caller 1336 return $OptList->GetHtml();
1365 # sanitize qualifier ID or grab it from object 1366 $QualifierIdOrObject = is_object($QualifierIdOrObject)
1367 ? $QualifierIdOrObject->Id() : intval($QualifierIdOrObject);
1369 # delete intersection records from database 1370 $this->DB->Query(
"DELETE FROM FieldQualifierInts" 1371 .
" WHERE QualifierId = ".$QualifierIdOrObject);
1381 # sanitize qualifier ID or grab it from object 1382 $QualifierIdOrObject = is_object($QualifierIdOrObject)
1383 ? $QualifierIdOrObject->Id() : intval($QualifierIdOrObject);
1385 # determine whether any fields use qualifier as default 1386 $DefaultCount = $this->DB->Query(
"SELECT COUNT(*) AS RecordCount" 1387 .
" FROM MetadataFields" 1388 .
" WHERE DefaultQualifier = ".$QualifierIdOrObject,
1391 # determine whether any fields are associated with qualifier 1392 $AssociationCount = $this->DB->Query(
"SELECT COUNT(*) AS RecordCount" 1393 .
" FROM FieldQualifierInts" 1394 .
" WHERE QualifierId = ".$QualifierIdOrObject,
1397 # report whether qualifier is in use based on defaults and associations 1398 return (($DefaultCount + $AssociationCount) > 0) ? TRUE : FALSE;
1419 if ($FieldId !== NULL)
1421 self::$FieldMappings[$this->Id][$MappedName] = $FieldId;
1423 return isset(self::$FieldMappings[$this->
Id][$MappedName])
1424 ? self::$FieldMappings[$this->Id][$MappedName] : NULL;
1437 foreach (self::$FieldMappings[$this->
Id] as $MappedName => $MappedFieldId)
1439 if ($MappedFieldId == $FieldId)
1481 $this->DB->Query(
"SELECT * FROM MetadataFields" 1482 .
" WHERE Owner IS NOT NULL AND LENGTH(Owner) > 0" 1483 .
" AND SchemaId = ".intval($this->
Id));
1485 while (FALSE !== ($Row = $this->DB->FetchRow()))
1487 $FieldId = $Row[
"FieldId"];
1488 $Fields[$FieldId] = $this->
GetField($FieldId);
1501 static $ValidFieldIds;
1503 # first time through, set up our lookup array 1504 if (!isset($ValidFieldIds))
1507 $DB->Query(
"SELECT FieldId FROM MetadataFields");
1508 $ValidFieldIds = array_flip(
$DB->FetchColumn(
"FieldId"));
1511 # if we were given a field id, check to see if it exists 1512 if (is_numeric($Field) &&
1513 array_key_exists($Field, $ValidFieldIds))
1518 # otherwise, try to look up this field 1521 $FieldId = self::GetCanonicalFieldIdentifier($Field);
1522 return array_key_exists($FieldId, $ValidFieldIds) ?
1525 catch (Exception $e)
1527 # if we can't find the field, then it doesn't exist 1549 # if field object was passed in 1552 # return identifier from field to caller 1553 return $Field->Id();
1555 # else if field ID was passed in 1556 elseif (is_numeric($Field))
1558 # return supplied field ID to caller 1561 # else if field name was passed in 1562 elseif (is_string($Field))
1564 # retrieve field names if not already loaded 1566 static $FieldNamesWithSchema;
1567 static $FieldSchemaIds;
1568 if (!isset($FieldNames))
1572 $DB->Query(
"SELECT SchemaId, Name FROM MetadataSchemas");
1573 $SchemaNames =
$DB->FetchColumn(
"Name",
"SchemaId");
1575 $DB->Query(
"SELECT FieldId, FieldName, SchemaId" 1576 .
" FROM MetadataFields");
1577 while ($Row =
$DB->FetchRow())
1579 if ($Row[
"SchemaId"] != self::SCHEMAID_DEFAULT)
1581 $FieldNamesWithSchema[$Row[
"FieldId"]] =
1582 $SchemaNames[$Row[
"SchemaId"]].
": ".
1585 $FieldNames[$Row[
"FieldId"]] = $Row[
"FieldName"];
1586 $FieldSchemaIds[$Row[
"FieldId"]] = $Row[
"SchemaId"];
1590 # look for the specified name with a schema prefix 1591 $Ids = array_keys($FieldNamesWithSchema, $Field);
1593 # if we find a unique schema-prefixed name, use that 1594 # (note that more than one schema-prefixed name shouldn't 1595 # be possible because fields must be unique inside a schema) 1596 if (count($Ids) == 1)
1598 return (
int)$Ids[0];
1600 elseif (count($Ids) > 1)
1602 throw new Exception(
"Multiple schema-name prefixed " 1603 .
"metadata fields found, which should be impossible.");
1606 # look for field with specified name 1607 $Ids = array_keys($FieldNames, $Field);
1609 # if one matching field was found 1610 $FieldsFound = count($Ids);
1611 if ($FieldsFound == 1)
1613 # return ID for matching field 1614 return (
int)$Ids[0];
1616 # else if multiple matching fields were found 1617 elseif ($FieldsFound > 1)
1619 # return ID of field with the lowest schema ID 1620 $LowestSchemaId = PHP_INT_MAX;
1621 foreach ($Ids as $Id)
1623 if ($FieldSchemaIds[$Id] < $LowestSchemaId)
1626 $LowestSchemaId = $FieldSchemaIds[$Id];
1631 # else error out because no matching field found 1634 throw new Exception(
"No metadata field found with the" 1635 .
" name \"".$Field.
"\".");
1638 # else error out because we were given an illegal field argument 1641 throw new InvalidArgumentException(
1642 "Illegal field argument supplied.");
1663 $Id = self::GetCanonicalFieldIdentifier($Field);
1665 # retrieve printable labels if not yet populated 1668 if (!isset($FieldNames))
1671 $DB->Query(
"SELECT SchemaId, Name FROM MetadataSchemas");
1672 $SchemaNames =
$DB->FetchColumn(
"Name",
"SchemaId");
1674 $DB->Query(
"SELECT SchemaId, FieldId, FieldName, Label FROM MetadataFields");
1675 while ($Row =
$DB->FetchRow())
1677 $SchemaPrefix = ($Row[
"SchemaId"] != self::SCHEMAID_DEFAULT)
1678 ? $SchemaNames[$Row[
"SchemaId"]].
": " :
"";
1680 $TrimmedLabel = trim($Row[
"Label"]);
1681 $FieldNames[$Row[
"FieldId"]] = $SchemaPrefix
1682 .(strlen($TrimmedLabel) ? $TrimmedLabel : $Row[
"FieldName"]);
1686 return isset($FieldNames[$Id]) ? $FieldNames[$Id] :
"" ;
1699 # start out assuming we won't find any values to translate 1700 $ReturnValues = array();
1702 # try to grab the specified field 1707 catch (Exception $e)
1709 # field no longer exists, so there are no values to translate 1710 return $ReturnValues;
1713 # if incoming value is not an array 1714 if (!is_array($Values))
1716 # convert incoming value to an array 1717 $Values = array($Values);
1720 # for each incoming value 1721 foreach ($Values as $Value)
1723 # look up value for index 1724 if ($Field->Type() == self::MDFTYPE_FLAG)
1726 # (for flag fields the value index (0 or 1) is used in Database) 1729 $ReturnValues[] =
"=".$Value;
1732 elseif ($Field->Type() == self::MDFTYPE_NUMBER)
1734 # (for flag fields the value index (0 or 1) is used in Database) 1737 $ReturnValues[] =
">=".$Value;
1740 elseif ($Field->Type() == self::MDFTYPE_USER)
1742 $User =
new CWUser(intval($Value));
1745 $ReturnValues[] =
"=".$User->Get(
"UserName");
1748 elseif ($Field->Type() == self::MDFTYPE_OPTION)
1750 if (!isset($PossibleFieldValues))
1752 $PossibleFieldValues = $Field->GetPossibleValues();
1755 if (isset($PossibleFieldValues[$Value]))
1757 $ReturnValues[] =
"=".$PossibleFieldValues[$Value];
1762 $NewValue = $Field->GetValueForId($Value);
1763 if ($NewValue !== NULL)
1765 $ReturnValues[] =
"=".$NewValue;
1770 # return array of translated values to caller 1771 return $ReturnValues;
1780 # fetch IDs of all metadata schemas 1782 $Database->Query(
"SELECT * FROM MetadataSchemas");
1783 $SchemaIds = $Database->FetchColumn(
"SchemaId");
1785 # return IDs to caller 1796 # fetch IDs of all metadata schemas 1797 $SchemaIds = self::GetAllSchemaIds();
1799 # construct objects from the IDs 1801 foreach ($SchemaIds as $SchemaId)
1806 # return schemas to caller 1817 if (is_callable($Callback))
1819 self::$OwnerListRetrievalFunction = $Callback;
1830 # if an owner list retrieval function and default schema exists 1831 if (self::$OwnerListRetrievalFunction
1832 && self::SchemaExistsWithId(self::SCHEMAID_DEFAULT))
1834 # retrieve the list of owners that currently exist 1835 $OwnerList = call_user_func(self::$OwnerListRetrievalFunction);
1837 # an array is expected 1838 if (is_array($OwnerList))
1842 # get each metadata field that is owned by a plugin 1843 $OwnedFields = $Schema->GetOwnedFields();
1845 # loop through each owned field 1846 foreach ($OwnedFields as $OwnedField)
1848 # the owner of the current field 1849 $Owner = $OwnedField->Owner();
1851 # if the owner of the field is in the list of owners that 1852 # currently exist, i.e., available plugins 1853 if (in_array($Owner, $OwnerList))
1855 # enable the field and reset its "enable on owner return" 1856 # flag if the "enable on owner return" flag is currently 1857 # set to true. in other words, re-enable the field since 1858 # the owner has returned to the list of existing owners 1859 if ($OwnedField->EnableOnOwnerReturn())
1861 $OwnedField->Enabled(TRUE);
1862 $OwnedField->EnableOnOwnerReturn(FALSE);
1866 # if the owner of the field is *not* in the list of owners 1867 # that currently exist, i.e., available plugins 1870 # first, see if the field is currently enabled since it 1871 # will determine whether the field is re-enabled when 1872 # the owner becomes available again 1873 $Enabled = $OwnedField->Enabled();
1875 # if the field is enabled, set its "enable on owner 1876 # return" flag to true and disable the field. nothing 1877 # needs to be done if the field is already disabled 1880 $OwnedField->EnableOnOwnerReturn($Enabled);
1881 $OwnedField->Enabled(FALSE);
1899 $this->FieldCompareDisplayOrder[$Field->Id()] = $Index++;
1906 $this->FieldCompareEditOrder[$Field->Id()] = $Index++;
1946 if ($this->FieldCompareType == self::MDFORDER_ALPHABETICAL)
1948 return ($FieldA->GetDisplayName() < $FieldB->GetDisplayName()) ? -1 : 1;
1951 if ($this->FieldCompareType == self::MDFORDER_EDITING)
1961 $PositionA = GetArrayValue($Order, $FieldA->Id(), 0);
1962 $PositionB = GetArrayValue($Order, $FieldB->Id(), 0);
1964 return $PositionA < $PositionB ? -1 : 1;
1968 # ---- PRIVATE INTERFACE ------------------------------------------------- 1972 private $AbbreviatedName;
1973 private $ResourceName;
1974 private $AuthoringPrivileges;
1975 private $EditingPrivileges;
1976 private $ViewingPrivileges;
1978 private $FieldCompareType;
1980 private $NewFields = array();
1981 private $ErrorMsgs = array();
1982 private static $FieldMappings = array();
2002 private function ConvertXmlToPrivilegeSet($Xml)
2004 # clear any existing errors 2005 if (array_key_exists(__METHOD__, $this->ErrorMsgs))
2006 { unset($this->ErrorMsgs[__METHOD__]); }
2008 # create new privilege set 2011 # for each XML child 2012 foreach ($Xml as $Tag => $Value)
2014 # take action based on element name 2017 case "PrivilegeSet":
2018 # convert child data to new set 2019 $NewSet = $this->ConvertXmlToPrivilegeSet($Value);
2021 # add new set to our privilege set 2022 $PrivSet->AddSet($NewSet);
2025 case "AddCondition":
2026 # start with default values for optional parameters 2027 unset($ConditionField);
2028 $ConditionValue = NULL;
2029 $ConditionOperator =
"==";
2031 # pull out parameters 2032 foreach ($Value as $ParamName => $ParamValue)
2034 $ParamValue = trim($ParamValue);
2038 $ConditionField = $this->
GetField($ParamValue, TRUE);
2039 if ($ConditionField === NULL)
2041 # record error about unknown field 2042 $this->ErrorMsgs[__METHOD__][] =
2043 "Unknown metadata field name found" 2044 .
" in AddCondition (".$ParamValue.
").";
2052 $ConditionValue = ($ParamValue ==
"NULL")
2053 ? NULL : (
string)$ParamValue;
2057 $ConditionOperator = (string)$ParamValue;
2061 # record error about unknown parameter name 2062 $this->ErrorMsgs[__METHOD__][] =
2063 "Unknown tag found in AddCondition (" 2073 if (!isset($ConditionField))
2075 # record error about no field value 2076 $this->ErrorMsgs[__METHOD__][] =
2077 "No metadata field specified in AddCondition.";
2083 # add conditional to privilege set 2084 $PrivSet->AddCondition($ConditionField,
2085 $ConditionValue, $ConditionOperator);
2089 # strip any excess whitespace off of value 2090 $Value = trim($Value);
2092 # if child looks like valid method name 2093 if (method_exists(
"PrivilegeSet", $Tag))
2095 # convert constants if needed 2096 if (defined($Value))
2098 $Value = constant($Value);
2100 # convert booleans if needed 2101 elseif (strtoupper($Value) ==
"TRUE")
2105 elseif (strtoupper($Value) ==
"FALSE")
2109 # convert privilege flag names if needed and appropriate 2110 elseif (preg_match(
"/Privilege$/", $Tag))
2113 if (!isset($Privileges))
2116 $Privileges = $PFactory->GetPrivileges(TRUE, FALSE);
2118 if (in_array($Value, $Privileges))
2120 $Value = array_search($Value, $Privileges);
2124 # set value using child data 2125 $PrivSet->$Tag((
string)$Value);
2129 # record error about bad tag 2130 $this->ErrorMsgs[__METHOD__][] =
2131 "Unknown tag encountered (".$Tag.
").";
2140 # return new privilege set to caller
GetHighestItemId($IgnoreSqlCondition=FALSE)
Retrieve highest item ID in use.
GetItemIdByName($Name, $IgnoreCase=FALSE)
Retrieve item ID by name.
SQL database abstraction object with smart query caching.
Factory which extracts all defined privileges from the database.
Set of privileges used to access resource information or other parts of the system.
ItemExists($ItemId, $IgnoreSqlCondition=FALSE)
Check that item exists with specified ID.
Represents a "resource" in CWIS.
static Singularize($Word)
Singularize an English word.
Common factory class for item manipulation.
NameIsInUse($Name, $IgnoreCase=FALSE)
Check whether item name is currently in use.
Factory for Resource objects.
CWIS-specific user class.
Convenience class for generating an HTML select/option form element.