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
15 # ---- PUBLIC INTERFACE --------------------------------------------------
17 # metadata field base types
18 # (must parallel MetadataFields.FieldType declaration in install/CreateTables.sql
19 # and MetadataField::$FieldTypeDBEnums declaration below)
36 # types of field ordering
59 # names used for display and edit orders
74 $this->
Id = $SchemaId;
76 # set up item factory base class
78 "MetadataField",
"MetadataFields",
"FieldId",
"FieldName", FALSE,
79 "SchemaId = ".intval($this->
Id()));
81 # load schema info from database
82 $this->DB->Query(
"SELECT * FROM MetadataSchemas"
83 .
" WHERE SchemaId = ".intval($SchemaId));
84 if ($this->DB->NumRowsSelected() < 1)
86 throw new Exception(
"Attempt to load metadata schema with "
87 .
" invalid ID (".$SchemaId.
").");
89 $Info = $this->DB->FetchRow();
90 $this->
Name = $Info[
"Name"];
96 # start with field info caching enabled
97 $this->CachingOn = TRUE;
111 # retrieve all constants for class
112 $Reflect =
new ReflectionClass(get_class());
113 $Constants = $Reflect->getConstants();
116 foreach ($Constants as $CName => $CValue)
118 # if value matches and prefix (if supplied) matches
119 if (($CValue == $Value)
120 && (($Prefix === NULL) || (strpos($CName, $Prefix) === 0)))
122 # return name to caller
127 # report to caller that no matching constant was found
150 $ResourceName = NULL)
152 # supply privilege settings if none provided
153 if ($AuthorPrivs === NULL) { $AuthorPrivs =
new PrivilegeSet(); }
154 if ($EditPrivs === NULL) { $EditPrivs =
new PrivilegeSet(); }
155 if ($ViewPrivs === NULL) { $ViewPrivs =
new PrivilegeSet(); }
157 # add schema to database
159 if (strtoupper($Name) ==
"DEFAULT")
161 $Id = self::SCHEMAID_DEFAULT;
163 elseif (strtoupper($Name) ==
"USER")
165 $Id = self::SCHEMAID_USER;
169 $Id =
$DB->Query(
"SELECT SchemaId FROM MetadataSchemas"
170 .
" ORDER BY SchemaId DESC LIMIT 1",
"SchemaId") + 1;
172 $DB->Query(
"INSERT INTO MetadataSchemas"
173 .
" (SchemaId, Name, ViewPage,"
174 .
" AuthoringPrivileges, EditingPrivileges, ViewingPrivileges)"
175 .
" VALUES (".intval($Id).
","
176 .
"'".addslashes($Name).
"',"
177 .
"'".
$DB->EscapeString($ViewPage).
"',"
178 .
"'".
$DB->EscapeString($AuthorPrivs->Data()).
"',"
179 .
"'".
$DB->EscapeString($EditPrivs->Data()).
"',"
180 .
"'".
$DB->EscapeString($ViewPrivs->Data()).
"')");
182 # construct the new schema
185 # set schema name if none supplied
188 $Schema->Name(
"Metadata Schema ".$Id);
191 # set the resource name if one is supplied
192 if (!is_null($ResourceName))
194 $Schema->ResourceName($ResourceName);
197 # create display and edit orders
201 # return the new schema
211 # delete fields associated with schema
212 $Fields = $this->
GetFields(NULL, NULL, TRUE, TRUE);
213 foreach ($Fields as $FieldId => $Field)
218 # delete metadata field orders associated with schema
224 # remove schema info from database
225 $this->DB->Query(
"DELETE FROM MetadataSchemas WHERE SchemaId = "
237 $DB->Query(
"SELECT * FROM MetadataSchemas"
238 .
" WHERE SchemaId = ".intval($SchemaId));
239 return (
$DB->NumRowsSelected() > 0) ? TRUE : FALSE;
249 # return value to caller
250 return intval($this->
Id);
258 function Name($NewValue = NULL)
260 # set new name if one supplied
261 if ($NewValue !== NULL)
263 $this->DB->Query(
"UPDATE MetadataSchemas"
264 .
" SET Name = '".addslashes($NewValue).
"'"
265 .
" WHERE SchemaId = '".intval($this->
Id).
"'");
266 $this->
Name = $NewValue;
269 # get the name if it hasn't been cached yet
270 if (!isset($this->
Name))
272 $this->
Name = $this->DB->Query(
"SELECT * FROM MetadataSchemas"
273 .
" WHERE SchemaId = '".intval($this->
Id).
"'",
"Name");
276 # return current value to caller
287 # set new resource name if one supplied
288 if ($NewValue !== NULL)
291 UPDATE MetadataSchemas
292 SET ResourceName = '".addslashes($NewValue).
"'
293 WHERE SchemaId = '".intval($this->
Id).
"'");
297 # get the name if it hasn't been cached yet
301 SELECT * FROM MetadataSchemas
302 WHERE SchemaId = '".intval($this->
Id).
"'",
305 # use the default resource name if one isn't set
312 # return current value to caller
313 return $this->ResourceName;
323 # set new viewing page if one supplied
324 if ($NewValue !== NULL)
326 $this->DB->Query(
"UPDATE MetadataSchemas"
327 .
" SET ViewPage = '".addslashes($NewValue).
"'"
328 .
" WHERE SchemaId = '".intval($this->
Id).
"'");
332 # get the view page if it hasn't been cached yet
335 $this->
ViewPage = $this->DB->Query(
"SELECT * FROM MetadataSchemas"
336 .
" WHERE SchemaId = '".intval($this->
Id).
"'",
"ViewPage");
339 # return current value to caller
340 return $this->ViewPage;
350 # if new privileges supplied
351 if ($NewValue !== NULL)
353 # store new privileges in database
354 $this->DB->Query(
"UPDATE MetadataSchemas"
355 .
" SET AuthoringPrivileges = '"
356 .$this->DB->EscapeString($NewValue->Data()).
"'"
357 .
" WHERE SchemaId = ".intval($this->
Id));
361 # return current value to caller
362 return $this->AuthoringPrivileges;
372 # if new privileges supplied
373 if ($NewValue !== NULL)
375 # store new privileges in database
376 $this->DB->Query(
"UPDATE MetadataSchemas"
377 .
" SET EditingPrivileges = '"
378 .$this->DB->EscapeString($NewValue->Data()).
"'"
379 .
" WHERE SchemaId = ".intval($this->
Id));
383 # return current value to caller
384 return $this->EditingPrivileges;
394 # if new privileges supplied
395 if ($NewValue !== NULL)
397 # store new privileges in database
398 $this->DB->Query(
"UPDATE MetadataSchemas"
399 .
" SET ViewingPrivileges = '"
400 .$this->DB->EscapeString($NewValue->Data()).
"'"
401 .
" WHERE SchemaId = ".intval($this->
Id));
405 # return current value to caller
406 return $this->ViewingPrivileges;
418 # get authoring privilege set for schema
421 # user can author if privileges are greater than resource set
422 $CanAuthor = $AuthorPrivs->MeetsRequirements($User);
424 # allow plugins to modify result of permission check
425 $SignalResult = $GLOBALS[
"AF"]->SignalEvent(
426 "EVENT_RESOURCE_AUTHOR_PERMISSION_CHECK", array(
429 "CanAuthor" => $CanAuthor));
430 $CanAuthor = $SignalResult[
"CanAuthor"];
432 # report back to caller whether user can author field
445 # get editing privilege set for schema
448 # user can edit if privileges are greater than resource set
449 $CanEdit = $EditPrivs->MeetsRequirements($User);
451 # allow plugins to modify result of permission check
452 $SignalResult = $GLOBALS[
"AF"]->SignalEvent(
453 "EVENT_RESOURCE_EDIT_PERMISSION_CHECK", array(
456 "CanEdit" => $CanEdit));
457 $CanEdit = $SignalResult[
"CanEdit"];
459 # report back to caller whether user can edit field
472 # get viewing privilege set for schema
475 # user can view if privileges are greater than resource set
476 $CanView = $ViewPrivs->MeetsRequirements($User);
478 # allow plugins to modify result of permission check
479 $SignalResult = $GLOBALS[
"AF"]->SignalEvent(
480 "EVENT_RESOURCE_VIEW_PERMISSION_CHECK", array(
483 "CanView" => $CanView));
484 $CanView = $SignalResult[
"CanView"];
486 # report back to caller whether user can view field
497 # get the query/GET parameters for the view page
498 $Query = parse_url($this->
ViewPage(), PHP_URL_QUERY);
500 # the URL couldn't be parsed
501 if (!is_string($Query))
506 # parse the GET parameters out of the query string
507 $GetVars = ParseQueryString($Query);
509 # search for the ID parameter
510 $Result = array_search(
"\$ID", $GetVars);
512 return $Result !== FALSE ? $Result : NULL;
529 # get the query/GET parameters for the view page
530 $Query = parse_url($this->
ViewPage(), PHP_URL_QUERY);
532 # can't perform matching if the URL couldn't be parsed
533 if (!is_string($Query))
538 # parse the GET parameters out of the query string
539 $GetVars = ParseQueryString($Query);
541 # now, get the query/GET parameters from the path given
542 $PathQuery = parse_url($Path, PHP_URL_QUERY);
544 # can't perform matching if the URL couldn't be parsed
545 if (!is_string($PathQuery))
550 # parse the GET parameters out of the path's query string
551 $PathGetVars = ParseQueryString($PathQuery);
553 # make sure the given path GET parameters contain at least the GET
554 # parameters from the view page and that all non-variable parameters are
555 # equal. the path GET parameters may contain more, which is okay
556 foreach ($GetVars as $GetVarName => $GetVarValue)
558 # there's a required parameter that is not included in the path GET
560 if (!array_key_exists($GetVarName, $PathGetVars))
565 # require the path's value to be equal to the view page's value if
566 # the view page's value is not a variable,
567 if ($PathGetVars[$GetVarName] != $GetVarValue
568 && (!strlen($GetVarValue) || $GetVarValue{0} !=
"$"))
574 # the path matches the view page path
584 $this->CachingOn = $NewValue;
596 function AddField($FieldName, $FieldType, $Optional = TRUE, $DefaultValue = NULL)
598 # clear any existing error messages
599 if (array_key_exists(__METHOD__, $this->ErrorMsgs))
600 { unset($this->ErrorMsgs[__METHOD__]); }
606 $FieldName, $Optional, $DefaultValue);
608 catch (Exception $Exception)
610 $this->ErrorMsgs[__METHOD__][] = $Exception->getMessage();
614 # return new field to caller
632 # clear loading status
634 if (array_key_exists(__METHOD__, $this->ErrorMsgs))
635 { unset($this->ErrorMsgs[__METHOD__]); }
637 # check that file exists and is readable
638 if (!file_exists($FileName))
640 $this->ErrorMsgs[__METHOD__][] =
"Could not find XML file '"
644 elseif (!is_readable($FileName))
646 $this->ErrorMsgs[__METHOD__][] =
"Could not read from XML file '"
652 libxml_use_internal_errors(TRUE);
653 $XmlData = simplexml_load_file($FileName);
654 $Errors = libxml_get_errors();
655 libxml_use_internal_errors(FALSE);
658 if ($XmlData === FALSE)
660 # retrieve XML error messages
661 foreach ($Errors as $Err)
663 $ErrType = ($Err->level == LIBXML_ERR_WARNING) ?
"Warning"
664 : (($Err->level == LIBXML_ERR_WARNING) ?
"Error"
666 $this->ErrorMsgs[__METHOD__][] =
"XML ".$ErrType.
": ".$Err->message
667 .
" (".$Err->file.
":".$Err->line.
",".$Err->column.
")";
670 # else if no metadata fields found record error message
671 elseif (!count($XmlData->MetadataField))
673 $this->ErrorMsgs[__METHOD__][] =
"No metadata fields found.";
675 # else process metadata fields
678 # for each metadata field entry found
681 foreach ($XmlData->MetadataField as $FieldXml)
685 # pull out field type if present
686 if (isset($FieldXml->Type))
688 $FieldType =
"MetadataSchema::".$FieldXml->Type;
689 if (!defined($FieldType))
691 $FieldType =
"MetadataSchema::MDFTYPE_"
692 .strtoupper(preg_replace(
"/\\s+/",
"",
697 # if required values are missing
698 if (!isset($FieldXml->Name) || !isset($FieldXml->Type)
699 || !defined($FieldType))
701 # add error message about required value missing
702 if (!isset($FieldXml->Name))
704 $this->ErrorMsgs[__METHOD__][] =
705 "Field name not found (MetadataField #"
710 $this->ErrorMsgs[__METHOD__][] =
711 "Valid type not found for field '"
712 .$FieldXml->Name.
"' (MetadataField #"
716 # else if there is not already a field with this name
717 elseif (!$this->
NameIsInUse(trim($FieldXml->Name)))
720 $Field = $this->
AddField($FieldXml->Name, constant($FieldType));
722 # if field creation failed
725 # add any error message to our error list
727 foreach ($ErrorMsgs as $Msg)
729 $this->ErrorMsgs[__METHOD__][] =
735 # add field to list of created fields
738 # for other field attributes
739 foreach ($FieldXml as $MethodName => $Value)
741 # if tags look valid and have not already been set
742 if (method_exists($Field, $MethodName)
743 && ($MethodName !=
"Name")
744 && ($MethodName !=
"Type"))
746 # if tag indicates privilege set
747 if (preg_match(
"/^[a-z]+Privileges\$/i",
750 # save element for later processing
751 $PrivilegesToSet[$Field->Id()][$MethodName] = $Value;
755 # condense down any extraneous whitespace
756 $Value = preg_replace(
"/\s+/",
" ", trim($Value));
758 # set value for field
759 $Field->$MethodName($Value);
764 # save the temp ID so that any privileges to set can be
765 # mapped to the actual ID when the field is made
767 $TempId = $Field->Id();
769 # make new field permanent
770 $Field->IsTempItem(FALSE);
772 # map privileges to set to the permanent field ID
773 if (isset($PrivilegesToSet) &&
774 isset($PrivilegesToSet[$TempId]) )
776 # copy the privileges over
777 $PrivilegesToSet[$Field->Id()] =
778 $PrivilegesToSet[$TempId];
780 # remove the values for the temp ID
781 unset($PrivilegesToSet[$TempId]);
787 # if we have privileges to set
788 if (isset($PrivilegesToSet))
790 # for each field with privileges
791 foreach ($PrivilegesToSet as $FieldId => $Privileges)
793 # load the field for which to set the privileges
796 # for each set of privileges for field
797 foreach ($Privileges as $MethodName => $Value)
799 # convert privilege value
800 $Value = $this->ConvertXmlToPrivilegeSet($Value);
802 # if conversion failed
805 # add resulting error messages to our list
807 "ConvertXmlToPrivilegeSet");
808 foreach ($ErrorMsgs as $Msg)
810 $this->ErrorMsgs[__METHOD__][] =
811 $Msg.
" (ConvertXmlToPrivilegeSet)";
816 # set value for field
817 $Field->$MethodName($Value);
823 # if errors were found during creation
824 if (array_key_exists(__METHOD__, $this->ErrorMsgs) || $TestRun)
826 # remove any fields that were created
835 # report success or failure based on whether errors were recorded
836 return (array_key_exists(__METHOD__, $this->ErrorMsgs)) ? FALSE : TRUE;
846 return $this->NewFields;
860 if ($Method === NULL)
862 return $this->ErrorMsgs;
866 if (!method_exists($this, $Method))
868 throw new Exception(
"Error messages requested for non-existent"
869 .
" method (".$Method.
").");
871 return array_key_exists(__CLASS__.
"::".$Method, $this->ErrorMsgs)
872 ? $this->ErrorMsgs[__CLASS__.
"::".$Method] : array();
887 # assume field addition will fail
888 $Field = self::MDFSTAT_ERROR;
890 # add XML prefixes if needed
892 if (!preg_match(
"/^<\?xml/i", $Xml))
894 if (!preg_match(
"/^<document>/i", $Xml))
896 $Xml =
"<document>".$Xml.
"</document>";
898 $Xml =
"<?xml version='1.0'?".
">".$Xml;
902 $XmlData = simplexml_load_string($Xml);
904 # if required values are present
905 if (is_object($XmlData)
906 && isset($XmlData->Name)
907 && isset($XmlData->Type)
908 && constant(
"MetadataSchema::".$XmlData->Type))
910 # create the metadata field
913 constant(
"MetadataSchema::".$XmlData->Type));
915 # if field creation succeeded
918 # for other field attributes
919 foreach ($XmlData as $MethodName => $Value)
921 # if they look valid and have not already been set
922 if (method_exists($Field, $MethodName)
923 && ($MethodName !=
"Name")
924 && ($MethodName !=
"Type"))
926 # if tag indicates privilege set
927 if (preg_match(
"/^[a-z]+Privileges\$/i",
930 # save element for later processing
931 $PrivilegesToSet[$MethodName] = $Value;
935 # condense down any extraneous whitespace
936 $Value = preg_replace(
"/\s+/",
" ", trim($Value));
938 # set value for field
939 $Field->$MethodName($Value);
944 # make new field permanent
945 $Field->IsTempItem(FALSE);
947 # if we have privileges to set
948 if (isset($PrivilegesToSet))
950 # for each set of privileges for field
951 foreach ($PrivilegesToSet as $MethodName => $Value)
953 # convert privilege value
954 $Value = $this->ConvertXmlToPrivilegeSet($Value);
956 # if conversion failed
959 # add resulting error messages to our list
961 "ConvertXmlToPrivilegeSet");
962 foreach ($ErrorMsgs as $Msg)
964 $this->ErrorMsgs[__METHOD__][] =
965 $Msg.
" (ConvertXmlToPrivilegeSet)";
970 # set value for field
971 $Field->$MethodName($Value);
978 # return new field (if any) to caller
993 $AF->SignalEvent(
"EVENT_PRE_FIELD_DELETE",
994 array(
"FieldId" => $FieldId) );
1014 # if caching is off or field is not already loaded
1015 if (($this->CachingOn != TRUE) || !isset($Fields[$FieldId]))
1022 catch (Exception $Exception)
1024 $Fields[$FieldId] = NULL;
1028 # return field to caller
1029 return $Fields[$FieldId];
1041 return ($FieldId === NULL) ? NULL : $this->
GetField($FieldId);
1053 return ($FieldId === NULL) ? NULL : $this->
GetField($FieldId);
1065 static $FieldIdsByName;
1067 # if caching is off or field ID is already loaded
1068 if (($this->CachingOn != TRUE) || !isset($FieldIdsByName[$this->
Id][$FieldName]))
1070 # retrieve field ID from DB
1071 $Condition = $IgnoreCase
1072 ?
"WHERE LOWER(FieldName) = '".addslashes(strtolower($FieldName)).
"'"
1073 :
"WHERE FieldName = '".addslashes($FieldName).
"'";
1074 $Condition .=
" AND SchemaId = ".intval($this->
Id);
1075 $FieldIdsByName[$this->Id][$FieldName] = $this->DB->Query(
1076 "SELECT FieldId FROM MetadataFields ".$Condition,
"FieldId");
1079 return $FieldIdsByName[$this->Id][$FieldName];
1091 static $FieldIdsByLabel;
1093 # if caching is off or field ID is already loaded
1094 if (($this->CachingOn != TRUE) || !isset($FieldIdsByLabel[$FieldLabel]))
1096 # retrieve field ID from DB
1097 $Condition = $IgnoreCase
1098 ?
"WHERE LOWER(Label) = '".addslashes(strtolower($FieldLabel)).
"'"
1099 :
"WHERE Label = '".addslashes($FieldLabel).
"'";
1100 $Condition .=
" AND SchemaId = ".intval($this->
Id);
1101 $FieldIdsByLabel[$FieldLabel] = $this->DB->Query(
1102 "SELECT FieldId FROM MetadataFields ".$Condition,
"FieldId");
1105 return $FieldIdsByLabel[$FieldLabel];
1132 $IncludeDisabledFields = FALSE, $IncludeTempFields = FALSE)
1134 # create empty array to pass back
1137 # for each field type in database
1138 $this->DB->Query(
"SELECT FieldId, FieldType FROM MetadataFields"
1139 .
" WHERE SchemaId = ".intval($this->
Id)
1140 .(!$IncludeDisabledFields ?
" AND Enabled != 0" :
"")
1141 .(!$IncludeTempFields ?
" AND FieldId >= 0" :
""));
1142 while ($Record = $this->DB->FetchRow())
1144 # if field type is known
1147 # if no specific type requested or if field is of requested type
1148 if (($FieldTypes == NULL)
1152 # create field object and add to array to be passed back
1153 $Fields[$Record[
"FieldId"]] = $this->
GetField($Record[
"FieldId"]);
1158 # if field sorting requested
1159 if ($OrderType !== NULL)
1161 # update field comparison ordering if not set yet
1167 $this->FieldCompareType = $OrderType;
1169 # sort field array by requested order type
1170 uasort($Fields, array($this,
"CompareFieldOrder"));
1173 # return array of field objects to caller
1192 $IncludeDisabledFields = FALSE, $IncludeTempFields = FALSE)
1194 $Fields = $this->
GetFields($FieldTypes, $OrderType,
1195 $IncludeDisabledFields, $IncludeTempFields);
1197 $FieldNames = array();
1198 foreach($Fields as $Field)
1200 $FieldNames[$Field->Id()] = $Field->Name();
1224 $SelectedFieldId = NULL, $IncludeNullOption = TRUE,
1225 $AddEntries = NULL, $AllowMultiple = FALSE)
1227 # retrieve requested fields
1230 # transform field names to labels
1231 foreach ($FieldNames as $FieldId => $FieldName)
1233 $FieldNames[$FieldId] = $this->
GetField($FieldId)->GetDisplayName();
1236 # begin HTML option list
1237 $Html =
"<select id=\"".$OptionListName.
"\" name=\"".$OptionListName.
"\"";
1239 # if multiple selections should be allowed
1242 $Html .=
" multiple=\"multiple\"";
1247 if ($IncludeNullOption)
1249 $Html .=
"<option value=\"\">--</option>\n";
1252 # make checking for IDs simpler
1253 if (!is_array($SelectedFieldId))
1255 $SelectedFieldId = array($SelectedFieldId);
1258 # for each metadata field
1259 foreach ($FieldNames as $Id => $Name)
1261 # add entry for field to option list
1262 $Html .=
"<option value=\"".$Id.
"\"";
1263 if (in_array($Id, $SelectedFieldId)) { $Html .=
" selected"; }
1264 $Html .=
">".htmlspecialchars($Name).
"</option>\n";
1267 # if additional entries were requested
1270 foreach ($AddEntries as $Value => $Label)
1272 $Html .=
"<option value=\"".$Value.
"\"";
1273 if (in_array($Value, $SelectedFieldId))
1275 $Html .=
" selected";
1277 $Html .=
">".htmlspecialchars($Label).
"</option>\n";
1281 # end HTML option list
1282 $Html .=
"</select>\n";
1284 # return constructed HTML to caller
1314 # sanitize qualifier ID or grab it from object
1315 $QualifierIdOrObject = is_object($QualifierIdOrObject)
1316 ? $QualifierIdOrObject->Id() : intval($QualifierIdOrObject);
1318 # delete intersection records from database
1319 $this->DB->Query(
"DELETE FROM FieldQualifierInts"
1320 .
" WHERE QualifierId = ".$QualifierIdOrObject);
1330 # sanitize qualifier ID or grab it from object
1331 $QualifierIdOrObject = is_object($QualifierIdOrObject)
1332 ? $QualifierIdOrObject->Id() : intval($QualifierIdOrObject);
1334 # determine whether any fields use qualifier as default
1335 $DefaultCount = $this->DB->Query(
"SELECT COUNT(*) AS RecordCount"
1336 .
" FROM MetadataFields"
1337 .
" WHERE DefaultQualifier = ".$QualifierIdOrObject,
1340 # determine whether any fields are associated with qualifier
1341 $AssociationCount = $this->DB->Query(
"SELECT COUNT(*) AS RecordCount"
1342 .
" FROM FieldQualifierInts"
1343 .
" WHERE QualifierId = ".$QualifierIdOrObject,
1346 # report whether qualifier is in use based on defaults and associations
1347 return (($DefaultCount + $AssociationCount) > 0) ? TRUE : FALSE;
1368 if ($FieldId !== NULL)
1370 self::$FieldMappings[$MappedName] = $FieldId;
1372 return isset(self::$FieldMappings[$MappedName])
1373 ? self::$FieldMappings[$MappedName] : NULL;
1386 foreach (self::$FieldMappings as $MappedName => $MappedFieldId)
1388 if ($MappedFieldId == $FieldId)
1406 return (self::StdNameToFieldMapping($MappedName) == NULL) ? NULL
1419 return self::StdNameToFieldMapping($MappedName);
1430 $this->DB->Query(
"SELECT * FROM MetadataFields"
1431 .
" WHERE Owner IS NOT NULL AND LENGTH(Owner) > 0"
1432 .
" AND SchemaId = ".intval($this->
Id));
1434 while (FALSE !== ($Row = $this->DB->FetchRow()))
1436 $FieldId = $Row[
"FieldId"];
1437 $Fields[$FieldId] = $this->
GetField($FieldId);
1460 # if field object was passed in
1463 # return identifier from field to caller
1464 return $Field->Id();
1466 # else if field ID was passed in
1467 elseif (is_numeric($Field))
1469 # return supplied field ID to caller
1472 # else if field name was passed in
1473 elseif (is_string($Field))
1475 # retrieve field names if not already loaded
1477 static $FieldSchemaIds;
1478 if (!isset($FieldNames))
1481 $DB->Query(
"SELECT FieldId, FieldName, SchemaId"
1482 .
" FROM MetadataFields");
1483 while ($Row =
$DB->FetchRow())
1485 $FieldNames[$Row[
"FieldId"]] = $Row[
"FieldName"];
1486 $FieldSchemaIds[$Row[
"FieldId"]] = $Row[
"SchemaId"];
1490 # look for field with specified name
1491 $Ids = array_keys($FieldNames, $Field);
1493 # if one matching field was found
1494 $FieldsFound = count($Ids);
1495 if ($FieldsFound == 1)
1497 # return ID for matching field
1498 return (
int)$Ids[0];
1500 # else if multiple matching fields were found
1501 elseif ($FieldsFound > 1)
1503 # return ID of field with the lowest schema ID
1504 $LowestSchemaId = PHP_INT_MAX;
1505 foreach ($Ids as $Id)
1507 if ($FieldSchemaIds[$Id] < $LowestSchemaId)
1510 $LowestSchemaId = $FieldSchemaIds[$Id];
1515 # else error out because no matching field found
1518 throw new Exception(
"No metadata field found with the"
1519 .
" name \"".$Field.
"\".");
1522 # else error out because we were given an illegal field argument
1525 throw new InvalidArgumentException(
1526 "Illegal field argument supplied.");
1547 $Id = self::GetCanonicalFieldIdentifier($Field);
1549 # retrieve field labels and names if not already loaded
1550 static $FieldLabels;
1552 if (!isset($FieldNames))
1555 $DB->Query(
"SELECT FieldId, FieldName, Label FROM MetadataFields");
1556 while ($Row =
$DB->FetchRow())
1558 $FieldNames[$Row[
"FieldId"]] = $Row[
"FieldName"];
1559 $FieldLabels[$Row[
"FieldId"]] = $Row[
"Label"];
1563 # return field label if available otherwise return field name
1564 return isset($FieldLabels[$Id]) ? $FieldLabels[$Id] : $FieldNames[$Id];
1577 # fetch the IDs all of the metadata schemas
1578 $Database->Query(
"SELECT * FROM MetadataSchemas");
1579 $SchemaIds = $Database->FetchColumn(
"SchemaId");
1581 # construct objects from the IDs
1582 foreach ($SchemaIds as $SchemaId)
1597 if (is_callable($Callback))
1599 self::$OwnerListRetrievalFunction = $Callback;
1610 # if an owner list retrieval function and default schema exists
1611 if (self::$OwnerListRetrievalFunction
1612 && self::SchemaExistsWithId(self::SCHEMAID_DEFAULT))
1614 # retrieve the list of owners that currently exist
1615 $OwnerList = call_user_func(self::$OwnerListRetrievalFunction);
1617 # an array is expected
1618 if (is_array($OwnerList))
1622 # get each metadata field that is owned by a plugin
1623 $OwnedFields = $Schema->GetOwnedFields();
1625 # loop through each owned field
1626 foreach ($OwnedFields as $OwnedField)
1628 # the owner of the current field
1629 $Owner = $OwnedField->Owner();
1631 # if the owner of the field is in the list of owners that
1632 # currently exist, i.e., available plugins
1633 if (in_array($Owner, $OwnerList))
1635 # enable the field and reset its "enable on owner return"
1636 # flag if the "enable on owner return" flag is currently
1637 # set to true. in other words, re-enable the field since
1638 # the owner has returned to the list of existing owners
1639 if ($OwnedField->EnableOnOwnerReturn())
1641 $OwnedField->Enabled(TRUE);
1642 $OwnedField->EnableOnOwnerReturn(FALSE);
1646 # if the owner of the field is *not* in the list of owners
1647 # that currently exist, i.e., available plugins
1650 # first, see if the field is currently enabled since it
1651 # will determine whether the field is re-enabled when
1652 # the owner becomes available again
1653 $Enabled = $OwnedField->Enabled();
1655 # if the field is enabled, set its "enable on owner
1656 # return" flag to true and disable the field. nothing
1657 # needs to be done if the field is already disabled
1660 $OwnedField->EnableOnOwnerReturn($Enabled);
1661 $OwnedField->Enabled(FALSE);
1679 $this->FieldCompareDisplayOrder[$Field->Id()] = $Index++;
1686 $this->FieldCompareEditOrder[$Field->Id()] = $Index++;
1728 return ($FieldA->GetDisplayName() < $FieldB->GetDisplayName()) ? -1 : 1;
1741 $PositionA = GetArrayValue($Order, $FieldA->Id(), 0);
1742 $PositionB = GetArrayValue($Order, $FieldB->Id(), 0);
1744 return $PositionA < $PositionB ? -1 : 1;
1748 # ---- PRIVATE INTERFACE -------------------------------------------------
1752 private $ResourceName;
1753 private $AuthoringPrivileges;
1754 private $EditingPrivileges;
1755 private $ViewingPrivileges;
1757 private $FieldCompareType;
1759 private $NewFields = array();
1760 private $ErrorMsgs = array();
1761 private static $FieldMappings;
1781 private function ConvertXmlToPrivilegeSet($Xml)
1783 # clear any existing errors
1784 if (array_key_exists(__METHOD__, $this->ErrorMsgs))
1785 { unset($this->ErrorMsgs[__METHOD__]); }
1787 # create new privilege set
1790 # for each XML child
1791 foreach ($Xml as $Tag => $Value)
1793 # take action based on element name
1796 case "PrivilegeSet":
1797 # convert child data to new set
1798 $NewSet = $this->ConvertXmlToPrivilegeSet($Value);
1800 # add new set to our privilege set
1801 $PrivSet->AddSet($NewSet);
1804 case "AddCondition":
1805 # start with default values for optional parameters
1806 unset($ConditionField);
1807 $ConditionValue = NULL;
1808 $ConditionOperator =
"==";
1810 # pull out parameters
1811 foreach ($Value as $ParamName => $ParamValue)
1813 $ParamValue = trim($ParamValue);
1818 (
string)$ParamValue, TRUE);
1819 if ($ConditionField === NULL)
1821 # record error about unknown field
1822 $this->ErrorMsgs[__METHOD__][] =
1823 "Unknown metadata field name found"
1824 .
" in AddCondition (".$ParamValue.
").";
1832 $ConditionValue = ($ParamValue ==
"NULL")
1833 ? NULL : (
string)$ParamValue;
1837 $ConditionOperator = (string)$ParamValue;
1841 # record error about unknown parameter name
1842 $this->ErrorMsgs[__METHOD__][] =
1843 "Unknown tag found in AddCondition ("
1853 if (!isset($ConditionField))
1855 # record error about no field value
1856 $this->ErrorMsgs[__METHOD__][] =
1857 "No metadata field specified in AddCondition.";
1863 # add conditional to privilege set
1864 $PrivSet->AddCondition($ConditionField,
1865 $ConditionValue, $ConditionOperator);
1869 # strip any excess whitespace off of value
1870 $Value = trim($Value);
1872 # if child looks like valid method name
1873 if (method_exists(
"PrivilegeSet", $Tag))
1875 # convert constants if needed
1876 if (defined($Value)) { $Value = constant($Value); }
1878 # convert booleans if needed
1879 if (strtoupper($Value) ==
"TRUE") { $Value = TRUE; }
1880 elseif (strtoupper($Value) ==
"FALSE") { $Value = FALSE; }
1882 # set value using child data
1883 $PrivSet->$Tag((
string)$Value);
1887 # record error about bad tag
1888 $this->ErrorMsgs[__METHOD__][] =
1889 "Unknown tag encountered (".$Tag.
").";
1898 # return new privilege set to caller
GetHighestItemId($IgnoreSqlCondition=FALSE)
Retrieve highest item ID in use.
SQL database abstraction object with smart query caching.
Set of privileges used to access resource information or other parts of the system.
Common factory class for item manipulation.
NameIsInUse($Name, $IgnoreCase=FALSE)
Check whether item name is currently in use.
ItemFactory($ItemClassName, $ItemTableName, $ItemIdFieldName, $ItemNameFieldName=NULL, $OrderOpsAllowed=FALSE, $SqlCondition=NULL)
Class constructor.