3 # FILE: MetadataField.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 # Update methods for timestamp fields
24 # values for the *UserIsValue fields
34 function Status() {
return $this->ErrorStatus; }
44 # if new value supplied
47 $this->DBFields[
"FieldType"]]))
49 # update database fields and store new type
50 $this->ModifyField(NULL, $NewValue);
53 # return type to caller
63 return $this->DBFields[
"FieldType"];
72 return $this->DBFields[
"SchemaId"];
93 # if new name specified
95 && trim($NewName) != $this->DBFields[
"FieldName"])
97 $NewName = trim($NewName);
98 $NormalizedName = $this->NormalizeFieldNameForDB(strtolower($NewName));
100 # if field name is invalid
101 if (!preg_match(
"/^[[:alnum:] \(\)]+$/", $NewName))
103 # set error status to indicate illegal name
107 # if the new name is a reserved word
108 else if ($NormalizedName ==
"resourceid" || $NormalizedName ==
"schemaid")
110 # set error status to indicate illegal name
114 # the name is okay but might be a duplicate
117 # check for duplicate name
118 $DuplicateCount = $this->DB->Query(
119 "SELECT COUNT(*) AS RecordCount FROM MetadataFields"
120 .
" WHERE FieldName = '".addslashes($NewName).
"'"
121 .
" AND SchemaId = ".intval($this->DBFields[
"SchemaId"]),
124 # if field name is duplicate
125 if ($DuplicateCount > 0)
127 # set error status to indicate duplicate name
132 # modify database declaration to reflect new field name
134 $this->ModifyField($NewName);
139 # return value to caller
140 return $this->DBFields[
"FieldName"];
150 $ValidValueExp =
'/^[[:alnum:] ]*$/';
151 $Value = $this->DBFields[
"Label"];
153 # if a new label was specified
154 if ($NewLabel !==
DB_NOVALUE && trim($NewLabel) != $Value)
156 $NewLabel = trim($NewLabel);
158 # if field label is valid
159 if (preg_match($ValidValueExp, $NewLabel))
161 $this->UpdateValue(
"Label", $NewLabel);
164 # the field label is invalid
181 # determine type list based on our type
182 switch ($this->
Type())
189 $AllowedTypes = array(
200 $AllowedTypes = array(
207 $AllowedTypes = array(
214 $AllowedTypes = array(
226 $AllowedTypes = array();
230 # return type list to caller
231 return $AllowedTypes;
244 $ItemTableName =
"MetadataFields";
245 $ItemIdFieldName =
"FieldId";
246 $ItemFactoryObjectName =
"MetadataSchema";
247 $ItemAssociationTables = array(
248 "FieldQualifierInts",
250 $ItemAssociationFieldName =
"MetadataFieldId";
252 # if new temp item setting supplied
253 if (!is_null($NewSetting))
255 # if caller requested to switch
256 if (($this->
Id() < 0 && $NewSetting == FALSE)
257 || ($this->
Id() >= 0 && $NewSetting == TRUE))
259 # if field name is invalid
260 if (strlen($this->NormalizeFieldNameForDB($this->
Name())) < 1)
262 # set error status to indicate illegal name
267 # lock DB tables to prevent next ID from being grabbed
270 LOCK TABLES ".$ItemTableName.
" WRITE,
271 APSessions WRITE, APSessionData WRITE,
272 MetadataSchemas WRITE");
274 # get next temp item ID
275 $OldItemId = $this->
Id();
276 $Factory =
new $ItemFactoryObjectName();
277 if ($NewSetting == TRUE)
279 $NewId = $Factory->GetNextTempItemId();
283 $NewId = $Factory->GetNextItemId();
287 $DB->Query(
"UPDATE ".$ItemTableName.
" SET ".$ItemIdFieldName.
" = ".
288 $NewId.
" WHERE ".$ItemIdFieldName.
" = ".$OldItemId);
291 $DB->Query(
"UNLOCK TABLES");
293 # change associations
294 foreach ($ItemAssociationTables as $TableName)
296 $DB->Query(
"UPDATE ".$TableName.
" SET ".$ItemAssociationFieldName.
" = ".
297 $NewId.
" WHERE ".$ItemAssociationFieldName.
" = ".$OldItemId);
300 # if changing item from temp to non-temp
301 if ($NewSetting == FALSE)
303 # add any needed database fields and/or entries
304 $this->AddDatabaseFields();
306 # set field order values for new field
307 $Schema->GetDisplayOrder()->AppendItem($NewId,
"MetadataField");
308 $Schema->GetEditOrder()->AppendItem($NewId,
"MetadataField");
311 # update metadata field id
312 $this->DBFields[
"FieldId"] = $NewId;
317 # report to caller whether we are a temp item
318 return ($this->
Id() < 0) ? TRUE : FALSE;
328 # if new privileges supplied
329 if ($NewValue !== NULL)
331 # store new privileges in database
332 $this->UpdateValue(
"AuthoringPrivileges", $NewValue->Data());
336 # return current value to caller
337 return $this->AuthoringPrivileges;
347 # if new privileges supplied
348 if ($NewValue !== NULL)
350 # store new privileges in database
351 $this->UpdateValue(
"EditingPrivileges", $NewValue->Data());
355 # return current value to caller
356 return $this->EditingPrivileges;
366 # if new privileges supplied
367 if ($NewValue !== NULL)
369 # store new privileges in database
370 $this->UpdateValue(
"ViewingPrivileges", $NewValue->Data());
374 # return current value to caller
375 return $this->ViewingPrivileges;
385 # if new privileges supplied
386 if ($NewValue !== NULL)
388 # store new privileges in database
389 $this->UpdateValue(
"PreviewingPrivileges", $NewValue->Data());
393 # return current value to caller
394 return $this->PreviewingPrivileges;
401 function Id() {
return $this->Id; }
416 {
return $this->UpdateValue(
"Description", $NewValue); }
424 {
return $this->UpdateValue(
"Instructions", $NewValue); }
432 {
return $this->UpdateValue(
"Owner", $NewValue); }
441 {
return $this->UpdateBoolValue(
"Enabled", $NewValue); }
450 {
return $this->UpdateBoolValue(
"Optional", $NewValue); }
459 {
return $this->UpdateBoolValue(
"Editable", $NewValue); }
468 {
return $this->UpdateBoolValue(
"AllowMultiple", $NewValue); }
477 {
return $this->UpdateBoolValue(
"IncludeInKeywordSearch", $NewValue); }
486 {
return $this->UpdateBoolValue(
"IncludeInAdvancedSearch", $NewValue); }
495 {
return $this->UpdateBoolValue(
"IncludeInFacetedSearch", $NewValue); }
504 {
return $this->UpdateBoolValue(
"IncludeInSortOptions", $NewValue); }
513 {
return $this->UpdateBoolValue(
"IncludeInRecommender", $NewValue); }
515 {
return $this->UpdateIntValue(
"TextFieldSize", $NewValue); }
517 {
return $this->UpdateIntValue(
"MaxLength", $NewValue); }
519 {
return $this->UpdateIntValue(
"ParagraphRows", $NewValue); }
521 {
return $this->UpdateIntValue(
"ParagraphCols", $NewValue); }
523 {
return $this->UpdateFloatValue(
"MinValue", $NewValue); }
525 {
return $this->UpdateFloatValue(
"MaxValue", $NewValue); }
527 {
return $this->UpdateValue(
"FlagOnLabel", $NewValue); }
529 {
return $this->UpdateValue(
"FlagOffLabel", $NewValue); }
531 {
return $this->UpdateValue(
"DateFormat", $NewValue); }
533 {
return $this->UpdateIntValue(
"SearchWeight", $NewValue); }
535 {
return $this->UpdateIntValue(
"RecommenderWeight", $NewValue); }
537 {
return $this->UpdateIntValue(
"MaxHeight", $NewValue); }
539 {
return $this->UpdateIntValue(
"MaxWidth", $NewValue); }
541 {
return $this->UpdateIntValue(
"MaxPreviewHeight", $NewValue); }
543 {
return $this->UpdateIntValue(
"MaxPreviewWidth", $NewValue); }
545 {
return $this->UpdateIntValue(
"MaxThumbnailHeight", $NewValue); }
547 {
return $this->UpdateIntValue(
"MaxThumbnailWidth", $NewValue); }
549 {
return $this->UpdateValue(
"DefaultAltText", $NewValue); }
551 {
return $this->UpdateBoolValue(
"UsesQualifiers", $NewValue); }
553 {
return $this->UpdateBoolValue(
"ShowQualifiers", $NewValue); }
555 {
return $this->UpdateValue(
"DefaultQualifier", $NewValue); }
557 {
return $this->UpdateBoolValue(
"AllowHTML", $NewValue); }
559 {
return $this->UpdateBoolValue(
"UseWysiwygEditor", $NewValue); }
561 {
return $this->UpdateBoolValue(
"UseForOaiSets", $NewValue); }
563 {
return $this->UpdateIntValue(
"OptionListThreshold", $NewValue); }
565 {
return $this->UpdateIntValue(
"AjaxThreshold", $NewValue); }
567 {
return $this->UpdateIntValue(
"NumAjaxResults", $NewValue); }
573 throw new Exception(
"Deprecated ".__METHOD__.
"() called -- ".
574 __METHOD__.
"s() should be used instead.");
581 throw new Exception(
"Deprecated ".__METHOD__.
"() called -- ".
582 __METHOD__.
"s() should be used instead.");
589 throw new Exception(
"Deprecated ".__METHOD__.
"() called -- ".
590 __METHOD__.
"s() should be used instead.");
593 {
return $this->UpdateConstValue(
"ImagePreviewPrivilege", $NewValue); }
599 throw new Exception(
"Deprecated ".__METHOD__.
"() called -- ".
600 "this should probably be using ViewingPrivileges() instead.");
603 {
return $this->UpdateBoolValue(
"EnableOnOwnerReturn", $NewValue); }
605 {
return $this->UpdateConstValue(
"ViewingUserIsValue", $NewValue,
"MetadataField"); }
607 {
return $this->UpdateConstValue(
"AuthoringUserIsValue", $NewValue,
"MetadataField"); }
609 {
return $this->UpdateConstValue(
"EditingUserIsValue", $NewValue,
"MetadataField"); }
611 {
return $this->UpdateIntValue(
"ViewingUserValue", $NewValue,
"MetadataField"); }
613 {
return $this->UpdateIntValue(
"AuthoringUserValue", $NewValue,
"MetadataField"); }
615 {
return $this->UpdateIntValue(
"EditingUserValue", $NewValue,
"MetadataField"); }
617 {
return $this->UpdateBoolValue(
"RequiredBySPT", $NewValue); }
624 $NewValue = serialize((array) $NewValue);
627 $Value = $this->UpdateValue(
"UserPrivilegeRestrictions", $NewValue);
632 $Value = (array) unserialize($Value);
635 # no value set, set it to an empty array
649 $OldValue = $this->UpdateValue(
"PointPrecision",
DB_NOVALUE);
651 if ($NewValue != $OldValue)
653 $Decimals = $this->UpdateValue(
"PointDecimalDigits",
DB_NOVALUE);
654 $TotalDigits = $NewValue + $Decimals;
656 $this->DB->Query(
"ALTER TABLE Resources MODIFY COLUMN "
657 .
"`".$this->DBFields[
"DBFieldName"].
"X` "
658 .
"DECIMAL(".$TotalDigits.
",".$Decimals.
")");
659 $this->DB->Query(
"ALTER TABLE Resources MODIFY COLUMN "
660 .
"`".$this->DBFields[
"DBFieldName"].
"Y` "
661 .
"DECIMAL(".$TotalDigits.
",".$Decimals.
")");
665 return $this->UpdateValue(
"PointPrecision", $NewValue);
673 $OldValue = $this->UpdateValue(
"PointDecimalDigits",
DB_NOVALUE);
675 if ($NewValue != $OldValue)
677 $Precision = $this->UpdateValue(
"PointPrecision",
DB_NOVALUE);
679 $TotalDigits = $NewValue + $Precision;
681 $this->DB->Query(
"ALTER TABLE Resources MODIFY COLUMN "
682 .
"`".$this->DBFields[
"DBFieldName"].
"X` "
683 .
"DECIMAL(".$TotalDigits.
",".$NewValue.
")");
684 $this->DB->Query(
"ALTER TABLE Resources MODIFY COLUMN "
685 .
"`".$this->DBFields[
"DBFieldName"].
"Y` "
686 .
"DECIMAL(".$TotalDigits.
",".$NewValue.
")");
690 return $this->UpdateValue(
"PointDecimalDigits", $NewValue);
699 isset($NewValue[
"X"]) && isset($NewValue[
"Y"]))
701 $NewValue = $NewValue[
"X"].
",".$NewValue[
"Y"];
704 # invalid value given
710 $Value = $this->UpdateValue(
"DefaultValue", $NewValue);
712 if (is_array($Value))
714 $tmp = explode(
",", $Value);
718 return array(
"X" => $tmp[0],
"Y" => $tmp[1]);
722 return array(
"X" => NULL,
"Y" => NULL);
727 # multiple default values to set
728 if (is_array($NewValue))
731 if (count($NewValue) == 0)
736 # multiple defaults are allowed
739 $NewValue = serialize($NewValue);
742 # only one default is allowed so get the first one
745 $NewValue = array_shift($NewValue);
749 $Result = $this->UpdateValue(
"DefaultValue", $NewValue);
751 return empty($Result) || is_numeric($Result) ?
752 $Result : unserialize($Result);
755 return $this->UpdateValue(
"DefaultValue", $NewValue);
765 return $this->UpdateValue(
"UpdateMethod", $NewValue);
768 # get possible values (only meaningful for Trees, Controlled Names, Options,
770 # (index for returned array is IDs for values)
773 # retrieve values based on field type
774 switch ($this->
Type())
777 $QueryString =
"SELECT ClassificationId, ClassificationName"
778 .
" FROM Classifications WHERE FieldId = ".$this->
Id()
779 .
" ORDER BY ClassificationName";
780 if ($MaxNumberOfValues)
782 $QueryString .=
" LIMIT ".intval($MaxNumberOfValues).
" OFFSET "
785 $this->DB->Query($QueryString);
786 $PossibleValues = $this->DB->FetchColumn(
787 "ClassificationName",
"ClassificationId");
792 $QueryString =
"SELECT ControlledNameId, ControlledName"
793 .
" FROM ControlledNames WHERE FieldId = ".$this->
Id()
794 .
" ORDER BY ControlledName";
795 if ($MaxNumberOfValues)
797 $QueryString .=
" LIMIT ".intval($MaxNumberOfValues).
" OFFSET "
800 $this->DB->Query($QueryString);
801 $PossibleValues = $this->DB->FetchColumn(
802 "ControlledName",
"ControlledNameId");
813 $PossibleValues = array();
815 if (count($Restrictions))
817 $PossibleValues = call_user_func_array(
818 array($UserFactory,
"GetUsersWithPrivileges"),
824 $Users = $UserFactory->GetMatchingUsers(
".*.");
826 foreach ($Users as $Id => $Data)
828 $PossibleValues[$Id] = $Data[
"UserName"];
835 # for everything else return an empty array
836 $PossibleValues = array();
840 # return array of possible values to caller
841 return $PossibleValues;
844 # get count of possible values (only meaningful for Trees, Controlled Names,
845 # Options, and Users)
848 # retrieve values based on field type
849 switch ($this->
Type())
852 $Count = $this->DB->Query(
"SELECT count(*) AS ValueCount"
853 .
" FROM Classifications WHERE FieldId = ".$this->
Id(),
859 $Count = $this->DB->Query(
"SELECT count(*) AS ValueCount"
860 .
" FROM ControlledNames WHERE FieldId = ".$this->
Id(),
873 # for everything else return an empty array
878 # return count of possible values to caller
882 # get ID for specified value (only meaningful for Trees / Controlled Names / Options)
883 # (returns NULL if value not found)
886 # retrieve ID based on field type
887 switch ($this->
Type())
890 $Id = $this->DB->Query(
"SELECT ClassificationId FROM Classifications"
891 .
" WHERE ClassificationName = '".addslashes($Value).
"'"
892 .
" AND FieldId = ".$this->
Id(),
898 $Id = $this->DB->Query(
"SELECT ControlledNameId FROM ControlledNames"
899 .
" WHERE ControlledName = '".addslashes($Value).
"'"
900 .
" AND FieldId = ".$this->
Id(),
905 # for everything else return NULL
910 # return ID for value to caller
914 # get value for specified ID (only meaningful for Trees / Controlled Names / Options)
915 # (returns NULL if ID not found)
918 # retrieve ID based on field type
919 switch ($this->
Type())
922 $Value = $this->DB->Query(
"SELECT ClassificationName FROM Classifications"
923 .
" WHERE ClassificationId = '".intval($Id).
"'"
924 .
" AND FieldId = ".$this->
Id(),
925 "ClassificationName");
930 $Value = $this->DB->Query(
"SELECT ControlledName FROM ControlledNames"
931 .
" WHERE ControlledNameId = '".intval($Id).
"'"
932 .
" AND FieldId = ".$this->
Id(),
937 # for everything else return NULL
942 # return ID for value to caller
958 # retrieve ID if object passed in
959 if (is_object($Value) && method_exists($Value,
"Id"))
961 $Value = $Value->Id();
964 # check value based on field type
965 $DBFieldName = $this->DBFields[
"DBFieldName"];
966 switch ($this->
Type())
977 $UseCount = $this->DB->Query(
"SELECT COUNT(*) AS UseCount"
979 .
" WHERE `".$DBFieldName.
"` = '".addslashes($Value).
"'"
980 .
" AND SchemaId = ".intval($this->DBFields[
"SchemaId"]),
985 $UseCount = $this->DB->Query(
"SELECT COUNT(*) AS UseCount"
986 .
" FROM ResourceClassInts"
987 .
" WHERE ClassificationId = ".intval($Value),
993 $UseCount = $this->DB->Query(
"SELECT COUNT(*) AS UseCount"
994 .
" FROM ResourceNameInts"
995 .
" WHERE ControlledNameId = ".intval($Value),
1000 $UseCount = $this->DB->Query(
"SELECT COUNT(*) AS UseCount"
1002 .
" WHERE `".$DBFieldName.
"X` = '".$Value[
"X"].
"'"
1003 .
" AND `".$DBFieldName.
"Y` = '".$Value[
"Y"].
"'"
1004 .
" AND SchemaId = ".intval($this->DBFields[
"SchemaId"]),
1009 throw new Exception(__CLASS__.
"::".__METHOD__.
"() called for"
1010 .
" unsupported field type (".$this->Type().
").");
1014 # report use count to caller
1018 # get/set whether field uses item-level qualifiers
1021 # if value provided different from present value
1023 && ($NewValue != $this->DBFields[
"HasItemLevelQualifiers"]))
1025 # check if qualifier column currently exists
1027 $QualColExists = $this->DB->FieldExists(
"Resources", $QualColName);
1029 # if new value indicates qualifiers should now be used
1030 if ($NewValue == TRUE)
1032 # if qualifier column does not exist in DB for this field
1033 if ($QualColExists == FALSE)
1035 # add qualifier column in DB for this field
1036 $this->DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
1037 .$QualColName.
"` INT");
1042 # if qualifier column exists in DB for this field
1043 if ($QualColExists == TRUE)
1045 # remove qualifier column from DB for this field
1046 $this->DB->Query(
"ALTER TABLE Resources DROP COLUMN `"
1052 return $this->UpdateValue(
"HasItemLevelQualifiers", $NewValue);
1055 # get list of qualifiers associated with field
1058 # start with empty list
1061 # for each associated qualifier
1062 $this->DB->Query(
"SELECT QualifierId FROM FieldQualifierInts"
1063 .
" WHERE MetadataFieldId = ".$this->DBFields[
"FieldId"]);
1064 while ($Record = $this->DB->FetchRow())
1066 # load qualifier object
1067 $Qual =
new Qualifier($Record[
"QualifierId"]);
1069 # add qualifier ID and name to list
1070 $List[$Qual->Id()] = $Qual->Name();
1073 # return list to caller
1077 # get list of qualifiers not associated with field
1080 # grab list of associated qualifiers
1083 # get list of all qualifiers
1085 $AllQualifiers = $QFactory->GetItemNames();
1087 # return list of unassociated qualifiers
1088 return array_diff($AllQualifiers, $AssociatedQualifiers);
1097 # if qualifier object passed in
1098 if (is_object($Qualifier))
1100 # grab qualifier ID from object
1101 $Qualifier = $Qualifier->Id();
1103 # else if string passed in does not look like ID
1104 elseif (!preg_match(
'/^[0-9]+$/', $Qualifier))
1106 # assume string passed in is name and use it to retrieve ID
1108 $Qualifier = $QFact->GetItemIdByName($Qualifier);
1111 # if not already associated
1112 $RecordCount = $this->DB->Query(
1113 "SELECT COUNT(*) AS RecordCount FROM FieldQualifierInts"
1114 .
" WHERE QualifierId = ".$Qualifier
1115 .
" AND MetadataFieldId = ".$this->
Id(),
"RecordCount");
1116 if ($RecordCount < 1)
1118 # associate field with qualifier
1119 $this->DB->Query(
"INSERT INTO FieldQualifierInts SET"
1120 .
" QualifierId = ".$Qualifier.
","
1121 .
" MetadataFieldId = ".$this->Id());
1132 # delete qualifier association
1135 # if qualifier object passed in
1136 if (is_object($QualifierIdOrObject))
1138 # grab qualifier ID from object
1139 $QualifierIdOrObject = $QualifierIdOrObject->Id();
1142 # delete intersection record from database
1143 $this->DB->Query(
"DELETE FROM FieldQualifierInts WHERE QualifierId = "
1144 .$QualifierIdOrObject.
" AND MetadataFieldId = ".
1148 # retrieve item factory object for this field
1151 switch ($this->
Type())
1176 # the field should not be viewed if it is disabled
1182 $UserPrivs = $GLOBALS[
"G_User"]->Privileges();
1184 # the user can view the field if they can edit it
1185 if ($UserPrivs->IsGreaterThan($this->EditingPrivileges()))
1190 # if the user can view the field
1191 if ($UserPrivs->IsGreaterThan($this->ViewingPrivileges()))
1196 # the user can't view the field
1200 # ---- PRIVATE INTERFACE -------------------------------------------------
1205 private $ErrorStatus;
1206 private $AuthoringPrivileges;
1207 private $EditingPrivileges;
1208 private $ViewingPrivileges;
1209 private $PreviewingPrivileges;
1232 # field type DB/PHP enum translations
1306 static function Create($SchemaId, $FieldType, $FieldName,
1307 $Optional = NULL, $DefaultValue = NULL)
1309 # error out if field type is bad
1312 throw new InvalidArgumentException(
"Bad field type (".$FieldType.
").");
1315 # error out if field name is duplicate
1317 $FieldName = trim($FieldName);
1318 $DuplicateCount = $DB->Query(
1319 "SELECT COUNT(*) AS RecordCount FROM MetadataFields"
1320 .
" WHERE FieldName = '".addslashes($FieldName).
"'"
1321 .
" AND SchemaId = ".intval($SchemaId),
1323 if ($DuplicateCount > 0)
1325 throw new InvalidArgumentException(
"Duplicate field name (".$FieldName.
").");
1328 # grab current user ID
1329 $UserId = $GLOBALS[
"G_User"]->Get(
"UserId");
1331 # normalize schema ID
1333 $SchemaId = $Schema->Id();
1335 # use schema privileges as starting privilege values
1336 $AuthorPrivs = $Schema->AuthoringPrivileges();
1337 $EditPrivs = $Schema->EditingPrivileges();
1338 $ViewPrivs = $Schema->ViewingPrivileges();
1339 $PreviewPrivs = $Schema->ViewingPrivileges();
1341 # lock DB tables and get next temporary field ID
1342 $DB->Query(
"LOCK TABLES MetadataFields WRITE");
1343 $FieldId = $Schema->GetNextTempItemId();
1345 # add field to MDF table in database
1346 $DB->Query(
"INSERT INTO MetadataFields"
1347 .
" (FieldId, SchemaId, FieldName, FieldType, LastModifiedById,"
1348 .
" Optional, AuthoringPrivileges, EditingPrivileges,"
1349 .
" ViewingPrivileges, PreviewingPrivileges)"
1351 .intval($FieldId).
", "
1352 .intval($SchemaId).
","
1353 .
" '".addslashes($FieldName).
"',"
1355 .intval($UserId).
", "
1356 .($Optional ?
"1" :
"0").
","
1357 .
"'".mysql_escape_string($AuthorPrivs->Data()).
"',"
1358 .
"'".mysql_escape_string($EditPrivs->Data()).
"',"
1359 .
"'".mysql_escape_string($ViewPrivs->Data()).
"',"
1360 .
"'".mysql_escape_string($PreviewPrivs->Data()).
"')");
1363 $DB->Query(
"UNLOCK TABLES");
1368 # set field defaults
1369 $Field->SetDefaults();
1371 # set the default value if specified
1372 if ($DefaultValue !== NULL)
1374 $Field->DefaultValue($DefaultValue);
1377 # return newly-constructed field to caller
1389 # assume everything will be okay
1392 # retrieve field info from database
1394 $Result = $this->DB->Query(
"SELECT * FROM MetadataFields"
1395 .
" WHERE FieldId = ".intval($FieldId));
1396 if ($this->DB->NumRowsSelected() == 0)
1398 throw new InvalidArgumentException(
"Invalid metadata field ID ("
1401 $Row = $this->DB->FetchRow();
1402 $this->DBFields = $Row;
1403 $this->
Id = $FieldId;
1405 # if privileges have not yet been initialized
1406 if (!strlen($this->DBFields[
"AuthoringPrivileges"]))
1408 # set default values for privileges from metadata schema
1417 # set privileges from stored values
1419 $Row[
"AuthoringPrivileges"]);
1421 $Row[
"EditingPrivileges"]);
1423 $Row[
"ViewingPrivileges"]);
1425 $Row[
"PreviewingPrivileges"]);
1428 # set database column name
1429 $this->DBFields[
"DBFieldName"] =
1430 $this->NormalizeFieldNameForDB($this->DBFields[
"FieldName"]);
1439 "Description" => NULL,
1440 "Instructions" => NULL,
1444 "AllowMultiple" => FALSE,
1445 "IncludeInKeywordSearch" => FALSE,
1446 "IncludeInAdvancedSearch" => FALSE,
1447 "IncludeInFacetedSearch" => FALSE,
1448 "IncludeInSortOptions" => TRUE,
1449 "IncludeInRecommender" => FALSE,
1450 "ParagraphRows" => 4,
1451 "ParagraphCols" => 50,
1453 "FlagOnLabel" =>
"On",
1454 "FlagOffLabel" =>
"Off",
1455 "DateFormat" => NULL,
1456 "RecommenderWeight" => 1,
1459 "MaxPreviewHeight" => 100,
1460 "MaxPreviewWidth" => 100,
1461 "MaxThumbnailHeight" => 50,
1462 "MaxThumbnailWidth" => 50,
1463 "DefaultAltText" => NULL,
1464 "UsesQualifiers" => FALSE,
1465 "HasItemLevelQualifiers" => FALSE,
1466 "ShowQualifiers" => FALSE,
1467 "DefaultQualifier" => NULL,
1468 "AllowHTML" => FALSE,
1469 "UseWysiwygEditor" => FALSE,
1470 "UseForOaiSets" => FALSE,
1471 "OptionListThreshold" => 25,
1472 "AjaxThreshold" => 50,
1473 "NumAjaxResults" => 50,
1474 "PointPrecision" => 8,
1475 "PointDecimalDigits" => 5,
1476 "UserPrivilegeRestrictions" => array(),
1477 "UpdateMethod" =>
"NoAutoUpdate",
1478 # 9999 is the
default max value because
default number field length is 4
1479 "MaxValue" => 9999);
1487 "DefaultValue" => NULL,
1488 "SearchWeight" => 1,
1489 "TextFieldSize" => 50,
1490 "MaxLength" => 100),
1492 "DefaultValue" => NULL,
1493 "SearchWeight" => 1,
1494 "TextFieldSize" => 50,
1495 "MaxLength" => 100),
1497 "DefaultValue" => NULL,
1498 "SearchWeight" => 1,
1499 "TextFieldSize" => 4,
1500 "MaxLength" => 100),
1502 "DefaultValue" => NULL,
1503 "SearchWeight" => 1,
1504 "TextFieldSize" => 10,
1505 "MaxLength" => 100),
1507 "DefaultValue" => NULL,
1508 "SearchWeight" => 1,
1509 "TextFieldSize" => 50,
1510 "MaxLength" => 100),
1512 "DefaultValue" => NULL,
1513 "SearchWeight" => 1,
1514 "TextFieldSize" => 50,
1515 "MaxLength" => 100),
1517 "DefaultValue" => NULL,
1518 "SearchWeight" => 1,
1519 "TextFieldSize" => 50,
1520 "MaxLength" => 100),
1522 "DefaultValue" => NULL,
1523 "SearchWeight" => 3,
1524 "TextFieldSize" => 50,
1525 "MaxLength" => 100),
1527 "DefaultValue" => NULL,
1528 "SearchWeight" => 3,
1529 "TextFieldSize" => 50,
1530 "MaxLength" => 100),
1532 "DefaultValue" => NULL,
1533 "SearchWeight" => 1,
1534 "TextFieldSize" => 50,
1535 "MaxLength" => 100),
1537 "DefaultValue" => NULL,
1538 "SearchWeight" => 1,
1539 "TextFieldSize" => 50,
1540 "MaxLength" => 100),
1542 "DefaultValue" => NULL,
1543 "SearchWeight" => 1,
1544 "TextFieldSize" => 50,
1545 "MaxLength" => 100),
1547 "DefaultValue" => NULL,
1548 "SearchWeight" => 1,
1549 "TextFieldSize" => 50,
1550 "MaxLength" => 255),
1552 "DefaultValue" => array(
"X" => NULL,
"Y" => NULL),
1553 "SearchWeight" => 1,
1554 "TextFieldSize" => 10,
1555 "MaxLength" => 100),
1557 "DefaultValue" => NULL,
1558 "SearchWeight" => 1,
1559 "TextFieldSize" => 50,
1560 "MaxLength" => 100));
1568 # set defaults that are the same for every field
1569 foreach (self::$FixedDefaults as $Key => $Value)
1571 $this->$Key($Value);
1574 # set defaults that depend on the type of the field
1575 foreach (self::$TypeBasedDefaults[$this->
Type()] as $Key => $Value)
1577 $this->$Key($Value);
1580 # tweak the update method if dealing with the date of record creation
1581 if ($this->
Name() ==
"Date Of Record Creation")
1587 # remove field from database (only for use by MetadataSchema object)
1590 # clear other database entries as appropriate for field type
1592 $DBFieldName = $this->DBFields[
"DBFieldName"];
1604 # remove field from resources table
1605 if ($DB->FieldExists(
"Resources", $DBFieldName))
1607 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"`");
1612 if ($DB->FieldExists(
"Resources", $DBFieldName.
"X"))
1614 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"X`");
1615 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"Y`");
1620 # remove fields from resources table
1621 if ($DB->FieldExists(
"Resources", $DBFieldName.
"Begin"))
1623 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"Begin`");
1624 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"End`");
1625 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"Precision`");
1630 $DB->Query(
"SELECT ClassificationId FROM Classifications "
1631 .
"WHERE FieldId = ".$this->
Id());
1633 while ($ClassificationId = $DB->FetchField(
"ClassificationId"))
1635 # remove any resource / name intersections
1636 $TempDB->Query(
"DELETE FROM ResourceClassInts WHERE "
1637 .
"ClassificationId = ".$ClassificationId);
1639 # remove controlled name
1640 $TempDB->Query(
"DELETE FROM Classifications WHERE "
1641 .
"ClassificationId = ".$ClassificationId);
1647 $DB->Query(
"SELECT ControlledNameId FROM ControlledNames "
1648 .
"WHERE FieldId = ".$this->
Id());
1650 while ($ControlledNameId = $DB->FetchField(
"ControlledNameId"))
1652 # remove any resource / name intersections
1653 $TempDB->Query(
"DELETE FROM ResourceNameInts WHERE "
1654 .
"ControlledNameId = ".$ControlledNameId);
1656 # remove any variant names
1657 $TempDB->Query(
"DELETE FROM VariantNames WHERE "
1658 .
"ControlledNameId = ".$ControlledNameId);
1660 # remove controlled name
1661 $TempDB->Query(
"DELETE FROM ControlledNames WHERE "
1662 .
"ControlledNameId = ".$ControlledNameId);
1667 # for each file associated with this field
1668 $DB->Query(
"SELECT FileId FROM Files WHERE FieldId = '".$this->
Id().
"'");
1669 while ($FileId = $DB->FetchRow())
1672 $File =
new File(intval($FileId));
1678 # remove any resource references for the field
1680 DELETE FROM ReferenceInts
1681 WHERE FieldId = '".addslashes($this->
Id()).
"'");
1685 # remove field from database
1686 $DB->Query(
"DELETE FROM MetadataFields "
1687 .
"WHERE FieldId = '".$this->DBFields[
"FieldId"].
"'");
1689 # remove any qualifier associations
1690 $DB->Query(
"DELETE FROM FieldQualifierInts WHERE MetadataFieldId = '"
1691 .$this->DBFields[
"FieldId"].
"'");
1693 # get the order objects the field is part of
1696 # remove it if it's a direct descendant
1697 $Order->RemoveItem($this->
Id(),
"MetadataField");
1699 # also make sure to remove it if it's part of a group
1700 foreach ($Order->GetItemIds() as $Item)
1702 if ($Item[
"Type"] ==
"MetadataFieldGroup")
1705 $Group->RemoveItem($this->
Id(),
"MetadataField");
1711 # modify any database fields
1712 private function ModifyField($NewName = NULL, $NewType = NULL)
1714 # grab old DB field name
1715 $OldDBFieldName = $this->DBFields[
"DBFieldName"];
1716 $OldFieldType = NULL;
1718 # if new field name supplied
1719 if ($NewName != NULL)
1721 # cache the old name for options and controllednames below
1722 $OldName = $this->DBFields[
"FieldName"];
1725 $this->UpdateValue(
"FieldName", $NewName);
1727 # determine new DB field name
1728 $NewDBFieldName = $this->NormalizeFieldNameForDB($NewName);
1730 # store new database field name
1731 $this->DBFields[
"DBFieldName"] = $NewDBFieldName;
1735 # set new field name equal to old field name
1736 $NewDBFieldName = $OldDBFieldName;
1739 # if new type supplied
1740 if ($NewType != NULL)
1742 # grab old field type
1745 # store new field type
1749 # if this is not a temporary field
1750 if ($this->
Id() >= 0)
1752 # modify field in DB as appropriate for field type
1760 # alter field declaration in Resources table
1761 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1762 .$OldDBFieldName.
"` `"
1763 .$NewDBFieldName.
"` TEXT "
1764 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1769 # alter field declaration in Resources table
1770 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1771 .$OldDBFieldName.
"` `"
1772 .$NewDBFieldName.
"` INT "
1773 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1777 $Precision = $this->UpdateValue(
"PointPrecision",
1779 $Digits = $this->UpdateValue(
"PointDecimalDigits",
1781 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN "
1782 .
"`".$OldDBFieldName.
"X` "
1783 .
"`".$NewDBFieldName.
"X`".
1784 " DECIMAL(".$Precision.
",".$Digits.
")");
1785 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN "
1786 .
"`".$OldDBFieldName.
"Y` "
1787 .
"`".$NewDBFieldName.
"Y`".
1788 " DECIMAL(".$Precision.
",".$Digits.
")");
1792 # if DB field name has changed
1793 if ($NewDBFieldName != $OldDBFieldName)
1795 # alter field declaration in Resources table
1796 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1797 .$OldDBFieldName.
"` `"
1798 .$NewDBFieldName.
"` TEXT");
1803 # alter field declaration in Resources table
1804 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1805 .$OldDBFieldName.
"` `"
1806 .$NewDBFieldName.
"` INT"
1809 # set any unset values to default
1810 $DB->Query(
"UPDATE Resources SET `".$NewDBFieldName
1812 .
" WHERE `".$NewDBFieldName.
"` IS NULL");
1816 # if new type supplied and new type is different from old
1817 if (($NewType != NULL) && ($NewType != $OldFieldType))
1819 # if old type was time stamp
1822 # change time stamp field in resources table to begin date
1823 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1824 .$OldDBFieldName.
"` `"
1825 .$NewDBFieldName.
"Begin` DATE "
1826 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1828 # add end date and precision fields
1829 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$NewDBFieldName.
"End"
1831 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$NewDBFieldName.
"Precision`"
1832 .
" INT ".($Optional ?
"" :
"NOT NULL"));
1834 # set precision to reflect time stamp content
1835 $DB->Query(
"UPDATE Resources SET `".$NewDBFieldName.
"Precision` = "
1840 exit(
"<br>ERROR: Attempt to convert metadata field to date from type other than timestamp<br>\n");
1845 # change name of fields
1846 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1847 .$OldDBFieldName.
"Begin` `"
1848 .$NewDBFieldName.
"Begin` DATE "
1849 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1850 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1851 .$OldDBFieldName.
"End` `"
1852 .$NewDBFieldName.
"End` DATE "
1853 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1854 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1855 .$OldDBFieldName.
"Precision` `"
1856 .$NewDBFieldName.
"Precision` INT "
1857 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1862 # if new type supplied and new type is different from old
1863 if (($NewType != NULL) && ($NewType != $OldFieldType))
1865 # if old type was date
1868 # change begin date field in resource table to time stamp
1869 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1870 .$OldDBFieldName.
"Begin` `"
1871 .$NewDBFieldName.
"` DATETIME "
1872 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1874 # drop end date and precision fields
1875 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `"
1876 .$OldDBFieldName.
"End`");
1877 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `"
1878 .$OldDBFieldName.
"Precision`");
1882 exit(
"<br>ERROR: Attempt to convert metadata field to time stamp from type other than date<br>\n");
1887 # change name of field
1888 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1889 .$OldDBFieldName.
"` `"
1890 .$NewDBFieldName.
"` DATETIME "
1891 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1903 # if qualifier DB field exists
1904 if ($DB->FieldExists(
"Resources", $OldDBFieldName.
"Qualifier"))
1906 # rename qualifier DB field
1907 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1908 .$OldDBFieldName.
"Qualifier` `"
1909 .$NewDBFieldName.
"Qualifier` INT ");
1914 # convenience functions to supply parameters to Database->UpdateValue()
1915 private function UpdateValue($FieldName, $NewValue)
1917 return $this->DB->UpdateValue(
"MetadataFields", $FieldName, $NewValue,
1918 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1921 private function UpdateIntValue($FieldName, $NewValue)
1923 return $this->DB->UpdateIntValue(
"MetadataFields", $FieldName, $NewValue,
1924 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1927 private function UpdateFloatValue($FieldName, $NewValue)
1929 return $this->DB->UpdateFloatValue(
"MetadataFields", $FieldName, $NewValue,
1930 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1933 private function UpdateBoolValue($FieldName, $NewValue)
1935 $NewValue = $this->TranslateStringToConstants($NewValue);
1936 return $this->DB->UpdateIntValue(
"MetadataFields", $FieldName, $NewValue,
1937 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1940 private function UpdateConstValue($FieldName, $NewValue, $ClassName=NULL)
1942 $NewValue = $this->TranslateStringToConstants($NewValue, $ClassName);
1943 return $this->DB->UpdateIntValue(
"MetadataFields", $FieldName, $NewValue,
1944 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1948 # normalize field name for use as database field name
1949 private function NormalizeFieldNameForDB($Name)
1951 return preg_replace(
"/[^a-z0-9]/i",
"", $Name)
1956 # add any needed database fields and/or entries
1957 private function AddDatabaseFields()
1959 # grab values for common use
1961 $FieldName = $this->
Name();
1966 # set up field(s) based on field type
1967 switch ($this->
Type())
1972 # add field to resources table (if not already present)
1973 if (!$DB->FieldExists(
"Resources", $DBFieldName))
1975 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1976 .
"` TEXT ".($Optional ?
"" :
"NOT NULL"));
1979 # if default value supplied
1980 if ($DefaultValue != NULL)
1982 # set all existing records to default value
1983 $DB->Query(
"UPDATE Resources SET `"
1984 .$DBFieldName.
"` = '".addslashes($DefaultValue).
"'");
1989 # add field to resources table (if not already present)
1990 if (!$DB->FieldExists(
"Resources", $DBFieldName))
1992 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1993 .
"` INT ".($Optional ?
"" :
"NOT NULL"));
1996 # if default value supplied
1997 if ($DefaultValue != NULL)
1999 # set all existing records to default value
2000 $DB->Query(
"UPDATE Resources SET `"
2001 .$DBFieldName.
"` = '".addslashes($DefaultValue).
"'");
2006 if (!$DB->FieldExists(
"Resources", $DBFieldName.
"X"))
2008 $Precision = $this->UpdateValue(
"PointPrecision",
2010 $Digits = $this->UpdateValue(
"PointDecimalDigits",
2013 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
2015 " DECIMAL(".$Precision.
",".$Digits.
")");
2016 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
2018 " DECIMAL(".$Precision.
",".$Digits.
")");
2023 # if field is not already present in database
2024 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2026 # add field to resources table
2027 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
2028 .
"` INT DEFAULT ".intval($DefaultValue));
2030 # set all existing records to default value
2031 $DB->Query(
"UPDATE Resources SET `"
2032 .$DBFieldName.
"` = ".intval($DefaultValue));
2037 # add field to resources table (if not already present)
2038 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2040 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
2041 .
"` INT ".($Optional ?
"" :
"NOT NULL"));
2046 # add fields to resources table (if not already present)
2047 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2049 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
2050 .$DBFieldName.
"` TEXT");
2055 # add fields to resources table (if not already present)
2056 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2058 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
2059 .$DBFieldName.
"` INT");
2064 # add fields to resources table (if not already present)
2065 if (!$DB->FieldExists(
"Resources", $DBFieldName.
"Begin"))
2067 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName.
"Begin`"
2068 .
" DATE ".($Optional ?
"" :
"NOT NULL"));
2070 if (!$DB->FieldExists(
"Resources", $DBFieldName.
"End"))
2072 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName.
"End`"
2075 if (!$DB->FieldExists(
"Resources", $DBFieldName.
"Precision"))
2077 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName.
"Precision`"
2078 .
" INT ".($Optional ?
"" :
"NOT NULL"));
2083 # add fields to resources table (if not already present)
2084 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2086 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
2087 .
"` DATETIME ".($Optional ?
"" :
"NOT NULL"));
2098 exit(
"<br>ERROR: Attempt to add database fields for illegal metadata field type<br>\n");
2110 private function TranslateStringToConstants($CString, $ClassName = NULL)
2112 # if not a string return value unchanged to caller
2113 if (!is_string($CString) || ($CString ===
DB_NOVALUE))
2115 $ReturnValue = $CString;
2117 # handle booleans as a special case
2118 elseif (strtoupper(trim($CString)) ==
"TRUE")
2120 $ReturnValue = TRUE;
2122 elseif (strtoupper(trim($CString)) ==
"FALSE")
2124 $ReturnValue = FALSE;
2128 # assume no values will be found
2129 $ReturnValue = NULL;
2131 # split apart any ORed-together values
2132 $Values = explode(
"|", $CString);
2134 # for each value found
2135 foreach ($Values as $Value)
2137 # trim off any extraneous whitespace
2138 $Value = trim($Value);
2140 # add class name prefix to constant name if requested
2141 if ($ClassName) { $Value = $ClassName.
"::".$Value; }
2143 # if value corresponds to a constant
2144 if (defined($Value))
2146 # add constant to return value
2147 $ReturnValue = ($ReturnValue === NULL)
2149 : ($ReturnValue | constant($Value));
2153 # if no corresponding constants were found
2154 if ($ReturnValue === NULL)
2156 # return original value to caller
2157 $ReturnValue = $CString;
2161 # return result to caller
2162 return $ReturnValue;
SQL database abstraction object with smart query caching.
Set of privileges used to access resource information or other parts of the system.
Factory class for Qualifier.
CWIS-specific user factory class.
Factory for manipulating ControlledName objects.
Factory for producing and manipulating Classification objects.
Class representing a stored (usually uploaded) file.