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 # Signal that a new (real) field was added:
310 array(
"FieldId" => $NewId ) );
312 # set field order values for new field
313 $Schema->GetDisplayOrder()->AppendItem($NewId,
"MetadataField");
314 $Schema->GetEditOrder()->AppendItem($NewId,
"MetadataField");
317 # update metadata field id
318 $this->DBFields[
"FieldId"] = $NewId;
324 # report to caller whether we are a temp item
325 return ($this->
Id() < 0) ? TRUE : FALSE;
335 # if new privileges supplied
336 if ($NewValue !== NULL)
338 # store new privileges in database
339 $this->UpdateValue(
"AuthoringPrivileges", $NewValue->Data());
343 # return current value to caller
344 return $this->AuthoringPrivileges;
354 # if new privileges supplied
355 if ($NewValue !== NULL)
357 # store new privileges in database
358 $this->UpdateValue(
"EditingPrivileges", $NewValue->Data());
362 # return current value to caller
363 return $this->EditingPrivileges;
373 # if new privileges supplied
374 if ($NewValue !== NULL)
376 # store new privileges in database
377 $this->UpdateValue(
"ViewingPrivileges", $NewValue->Data());
381 # return current value to caller
382 return $this->ViewingPrivileges;
392 # if new privileges supplied
393 if ($NewValue !== NULL)
395 # store new privileges in database
396 $this->UpdateValue(
"PreviewingPrivileges", $NewValue->Data());
400 # return current value to caller
401 return $this->PreviewingPrivileges;
408 function Id() {
return $this->Id; }
423 {
return $this->UpdateValue(
"Description", $NewValue); }
431 {
return $this->UpdateValue(
"Instructions", $NewValue); }
439 {
return $this->UpdateValue(
"Owner", $NewValue); }
448 {
return $this->UpdateBoolValue(
"Enabled", $NewValue); }
457 {
return $this->UpdateBoolValue(
"Optional", $NewValue); }
466 {
return $this->UpdateBoolValue(
"Editable", $NewValue); }
475 {
return $this->UpdateBoolValue(
"AllowMultiple", $NewValue); }
484 {
return $this->UpdateBoolValue(
"IncludeInKeywordSearch", $NewValue); }
493 {
return $this->UpdateBoolValue(
"IncludeInAdvancedSearch", $NewValue); }
502 {
return $this->UpdateBoolValue(
"IncludeInFacetedSearch", $NewValue); }
511 {
return $this->UpdateBoolValue(
"IncludeInSortOptions", $NewValue); }
520 {
return $this->UpdateBoolValue(
"IncludeInRecommender", $NewValue); }
522 {
return $this->UpdateIntValue(
"TextFieldSize", $NewValue); }
524 {
return $this->UpdateIntValue(
"MaxLength", $NewValue); }
526 {
return $this->UpdateIntValue(
"ParagraphRows", $NewValue); }
528 {
return $this->UpdateIntValue(
"ParagraphCols", $NewValue); }
530 {
return $this->UpdateFloatValue(
"MinValue", $NewValue); }
532 {
return $this->UpdateFloatValue(
"MaxValue", $NewValue); }
534 {
return $this->UpdateValue(
"FlagOnLabel", $NewValue); }
536 {
return $this->UpdateValue(
"FlagOffLabel", $NewValue); }
538 {
return $this->UpdateValue(
"DateFormat", $NewValue); }
540 {
return $this->UpdateIntValue(
"SearchWeight", $NewValue); }
542 {
return $this->UpdateIntValue(
"RecommenderWeight", $NewValue); }
544 {
return $this->UpdateIntValue(
"MaxHeight", $NewValue); }
546 {
return $this->UpdateIntValue(
"MaxWidth", $NewValue); }
548 {
return $this->UpdateIntValue(
"MaxPreviewHeight", $NewValue); }
550 {
return $this->UpdateIntValue(
"MaxPreviewWidth", $NewValue); }
552 {
return $this->UpdateIntValue(
"MaxThumbnailHeight", $NewValue); }
554 {
return $this->UpdateIntValue(
"MaxThumbnailWidth", $NewValue); }
556 {
return $this->UpdateValue(
"DefaultAltText", $NewValue); }
558 {
return $this->UpdateBoolValue(
"UsesQualifiers", $NewValue); }
560 {
return $this->UpdateBoolValue(
"ShowQualifiers", $NewValue); }
562 {
return $this->UpdateValue(
"DefaultQualifier", $NewValue); }
564 {
return $this->UpdateBoolValue(
"AllowHTML", $NewValue); }
566 {
return $this->UpdateBoolValue(
"UseWysiwygEditor", $NewValue); }
568 {
return $this->UpdateBoolValue(
"UseForOaiSets", $NewValue); }
570 {
return $this->UpdateBoolValue(
"DisplayAsListForAdvancedSearch", $NewValue); }
572 {
return $this->UpdateIntValue(
"OptionListThreshold", $NewValue); }
574 {
return $this->UpdateIntValue(
"AjaxThreshold", $NewValue); }
576 {
return $this->UpdateIntValue(
"NumAjaxResults", $NewValue); }
582 throw new Exception(
"Deprecated ".__METHOD__.
"() called -- ".
583 __METHOD__.
"s() should be used instead.");
590 throw new Exception(
"Deprecated ".__METHOD__.
"() called -- ".
591 __METHOD__.
"s() should be used instead.");
598 throw new Exception(
"Deprecated ".__METHOD__.
"() called -- ".
599 __METHOD__.
"s() should be used instead.");
602 {
return $this->UpdateConstValue(
"ImagePreviewPrivilege", $NewValue); }
608 throw new Exception(
"Deprecated ".__METHOD__.
"() called -- ".
609 "this should probably be using ViewingPrivileges() instead.");
612 {
return $this->UpdateBoolValue(
"EnableOnOwnerReturn", $NewValue); }
614 {
return $this->UpdateConstValue(
"ViewingUserIsValue", $NewValue,
"MetadataField"); }
616 {
return $this->UpdateConstValue(
"AuthoringUserIsValue", $NewValue,
"MetadataField"); }
618 {
return $this->UpdateConstValue(
"EditingUserIsValue", $NewValue,
"MetadataField"); }
620 {
return $this->UpdateIntValue(
"ViewingUserValue", $NewValue,
"MetadataField"); }
622 {
return $this->UpdateIntValue(
"AuthoringUserValue", $NewValue,
"MetadataField"); }
624 {
return $this->UpdateIntValue(
"EditingUserValue", $NewValue,
"MetadataField"); }
626 {
return $this->UpdateBoolValue(
"RequiredBySPT", $NewValue); }
633 $NewValue = serialize((array) $NewValue);
636 $Value = $this->UpdateValue(
"UserPrivilegeRestrictions", $NewValue);
641 $Value = (array) unserialize($Value);
644 # no value set, set it to an empty array
658 $OldValue = $this->UpdateValue(
"PointPrecision",
DB_NOVALUE);
660 if ($NewValue != $OldValue)
662 $Decimals = $this->UpdateValue(
"PointDecimalDigits",
DB_NOVALUE);
663 $TotalDigits = $NewValue + $Decimals;
665 $this->DB->Query(
"ALTER TABLE Resources MODIFY COLUMN "
666 .
"`".$this->DBFields[
"DBFieldName"].
"X` "
667 .
"DECIMAL(".$TotalDigits.
",".$Decimals.
")");
668 $this->DB->Query(
"ALTER TABLE Resources MODIFY COLUMN "
669 .
"`".$this->DBFields[
"DBFieldName"].
"Y` "
670 .
"DECIMAL(".$TotalDigits.
",".$Decimals.
")");
674 return $this->UpdateValue(
"PointPrecision", $NewValue);
682 $OldValue = $this->UpdateValue(
"PointDecimalDigits",
DB_NOVALUE);
684 if ($NewValue != $OldValue)
686 $Precision = $this->UpdateValue(
"PointPrecision",
DB_NOVALUE);
688 $TotalDigits = $NewValue + $Precision;
690 $this->DB->Query(
"ALTER TABLE Resources MODIFY COLUMN "
691 .
"`".$this->DBFields[
"DBFieldName"].
"X` "
692 .
"DECIMAL(".$TotalDigits.
",".$NewValue.
")");
693 $this->DB->Query(
"ALTER TABLE Resources MODIFY COLUMN "
694 .
"`".$this->DBFields[
"DBFieldName"].
"Y` "
695 .
"DECIMAL(".$TotalDigits.
",".$NewValue.
")");
699 return $this->UpdateValue(
"PointDecimalDigits", $NewValue);
708 isset($NewValue[
"X"]) && isset($NewValue[
"Y"]))
710 $NewValue = $NewValue[
"X"].
",".$NewValue[
"Y"];
713 # invalid value given
719 $Value = $this->UpdateValue(
"DefaultValue", $NewValue);
721 if (is_array($Value))
723 $tmp = explode(
",", $Value);
727 return array(
"X" => $tmp[0],
"Y" => $tmp[1]);
731 return array(
"X" => NULL,
"Y" => NULL);
736 # multiple default values to set
737 if (is_array($NewValue))
740 if (count($NewValue) == 0)
745 # multiple defaults are allowed
748 $NewValue = serialize($NewValue);
751 # only one default is allowed so get the first one
754 $NewValue = array_shift($NewValue);
758 $Result = $this->UpdateValue(
"DefaultValue", $NewValue);
760 return empty($Result) || is_numeric($Result) ?
761 $Result : unserialize($Result);
764 return $this->UpdateValue(
"DefaultValue", $NewValue);
774 return $this->UpdateValue(
"UpdateMethod", $NewValue);
777 # get possible values (only meaningful for Trees, Controlled Names, Options,
779 # (index for returned array is IDs for values)
782 # retrieve values based on field type
783 switch ($this->
Type())
786 $QueryString =
"SELECT ClassificationId, ClassificationName"
787 .
" FROM Classifications WHERE FieldId = ".$this->
Id()
788 .
" ORDER BY ClassificationName";
789 if ($MaxNumberOfValues)
791 $QueryString .=
" LIMIT ".intval($MaxNumberOfValues).
" OFFSET "
794 $this->DB->Query($QueryString);
795 $PossibleValues = $this->DB->FetchColumn(
796 "ClassificationName",
"ClassificationId");
801 $QueryString =
"SELECT ControlledNameId, ControlledName"
802 .
" FROM ControlledNames WHERE FieldId = ".$this->
Id()
803 .
" ORDER BY ControlledName";
804 if ($MaxNumberOfValues)
806 $QueryString .=
" LIMIT ".intval($MaxNumberOfValues).
" OFFSET "
809 $this->DB->Query($QueryString);
810 $PossibleValues = $this->DB->FetchColumn(
811 "ControlledName",
"ControlledNameId");
822 $PossibleValues = array();
824 if (count($Restrictions))
826 $PossibleValues = call_user_func_array(
827 array($UserFactory,
"GetUsersWithPrivileges"),
833 $Users = $UserFactory->GetMatchingUsers(
".*.");
835 foreach ($Users as $Id => $Data)
837 $PossibleValues[$Id] = $Data[
"UserName"];
844 # for everything else return an empty array
845 $PossibleValues = array();
849 # return array of possible values to caller
850 return $PossibleValues;
853 # get count of possible values (only meaningful for Trees, Controlled Names,
854 # Options, and Users)
857 # retrieve values based on field type
858 switch ($this->
Type())
861 $Count = $this->DB->Query(
"SELECT count(*) AS ValueCount"
862 .
" FROM Classifications WHERE FieldId = ".$this->
Id(),
868 $Count = $this->DB->Query(
"SELECT count(*) AS ValueCount"
869 .
" FROM ControlledNames WHERE FieldId = ".$this->
Id(),
882 # for everything else return an empty array
887 # return count of possible values to caller
891 # get ID for specified value (only meaningful for Trees / Controlled Names / Options)
892 # (returns NULL if value not found)
895 # retrieve ID based on field type
896 switch ($this->
Type())
899 $Id = $this->DB->Query(
"SELECT ClassificationId FROM Classifications"
900 .
" WHERE ClassificationName = '".addslashes($Value).
"'"
901 .
" AND FieldId = ".$this->
Id(),
907 $Id = $this->DB->Query(
"SELECT ControlledNameId FROM ControlledNames"
908 .
" WHERE ControlledName = '".addslashes($Value).
"'"
909 .
" AND FieldId = ".$this->
Id(),
914 # for everything else return NULL
919 # return ID for value to caller
923 # get value for specified ID (only meaningful for Trees / Controlled Names / Options)
924 # (returns NULL if ID not found)
927 # retrieve ID based on field type
928 switch ($this->
Type())
931 $Value = $this->DB->Query(
"SELECT ClassificationName FROM Classifications"
932 .
" WHERE ClassificationId = '".intval($Id).
"'"
933 .
" AND FieldId = ".$this->
Id(),
934 "ClassificationName");
939 $Value = $this->DB->Query(
"SELECT ControlledName FROM ControlledNames"
940 .
" WHERE ControlledNameId = '".intval($Id).
"'"
941 .
" AND FieldId = ".$this->
Id(),
946 # for everything else return NULL
951 # return ID for value to caller
967 # retrieve ID if object passed in
968 if (is_object($Value) && method_exists($Value,
"Id"))
970 $Value = $Value->Id();
973 # check value based on field type
974 $DBFieldName = $this->DBFields[
"DBFieldName"];
975 switch ($this->
Type())
986 $UseCount = $this->DB->Query(
"SELECT COUNT(*) AS UseCount"
988 .
" WHERE `".$DBFieldName.
"` = '".addslashes($Value).
"'"
989 .
" AND SchemaId = ".intval($this->DBFields[
"SchemaId"]),
994 $UseCount = $this->DB->Query(
"SELECT COUNT(*) AS UseCount"
995 .
" FROM ResourceClassInts"
996 .
" WHERE ClassificationId = ".intval($Value),
1002 $UseCount = $this->DB->Query(
"SELECT COUNT(*) AS UseCount"
1003 .
" FROM ResourceNameInts"
1004 .
" WHERE ControlledNameId = ".intval($Value),
1009 $UseCount = $this->DB->Query(
"SELECT COUNT(*) AS UseCount"
1011 .
" WHERE `".$DBFieldName.
"X` = '".$Value[
"X"].
"'"
1012 .
" AND `".$DBFieldName.
"Y` = '".$Value[
"Y"].
"'"
1013 .
" AND SchemaId = ".intval($this->DBFields[
"SchemaId"]),
1018 throw new Exception(__CLASS__.
"::".__METHOD__.
"() called for"
1019 .
" unsupported field type (".$this->Type().
").");
1023 # report use count to caller
1027 # get/set whether field uses item-level qualifiers
1030 # if value provided different from present value
1032 && ($NewValue != $this->DBFields[
"HasItemLevelQualifiers"]))
1034 # check if qualifier column currently exists
1036 $QualColExists = $this->DB->FieldExists(
"Resources", $QualColName);
1038 # if new value indicates qualifiers should now be used
1039 if ($NewValue == TRUE)
1041 # if qualifier column does not exist in DB for this field
1042 if ($QualColExists == FALSE)
1044 # add qualifier column in DB for this field
1045 $this->DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
1046 .$QualColName.
"` INT");
1051 # if qualifier column exists in DB for this field
1052 if ($QualColExists == TRUE)
1054 # remove qualifier column from DB for this field
1055 $this->DB->Query(
"ALTER TABLE Resources DROP COLUMN `"
1061 return $this->UpdateValue(
"HasItemLevelQualifiers", $NewValue);
1064 # get list of qualifiers associated with field
1067 # start with empty list
1070 # for each associated qualifier
1071 $this->DB->Query(
"SELECT QualifierId FROM FieldQualifierInts"
1072 .
" WHERE MetadataFieldId = ".$this->DBFields[
"FieldId"]);
1073 while ($Record = $this->DB->FetchRow())
1075 # load qualifier object
1076 $Qual =
new Qualifier($Record[
"QualifierId"]);
1078 # add qualifier ID and name to list
1079 $List[$Qual->Id()] = $Qual->Name();
1082 # return list to caller
1086 # get list of qualifiers not associated with field
1089 # grab list of associated qualifiers
1092 # get list of all qualifiers
1094 $AllQualifiers = $QFactory->GetItemNames();
1096 # return list of unassociated qualifiers
1097 return array_diff($AllQualifiers, $AssociatedQualifiers);
1106 # if qualifier object passed in
1107 if (is_object($Qualifier))
1109 # grab qualifier ID from object
1110 $Qualifier = $Qualifier->Id();
1112 # else if string passed in does not look like ID
1113 elseif (!preg_match(
'/^[0-9]+$/', $Qualifier))
1115 # assume string passed in is name and use it to retrieve ID
1117 $Qualifier = $QFact->GetItemIdByName($Qualifier);
1120 # if not already associated
1121 $RecordCount = $this->DB->Query(
1122 "SELECT COUNT(*) AS RecordCount FROM FieldQualifierInts"
1123 .
" WHERE QualifierId = ".$Qualifier
1124 .
" AND MetadataFieldId = ".$this->
Id(),
"RecordCount");
1125 if ($RecordCount < 1)
1127 # associate field with qualifier
1128 $this->DB->Query(
"INSERT INTO FieldQualifierInts SET"
1129 .
" QualifierId = ".$Qualifier.
","
1130 .
" MetadataFieldId = ".$this->Id());
1141 # delete qualifier association
1144 # if qualifier object passed in
1145 if (is_object($QualifierIdOrObject))
1147 # grab qualifier ID from object
1148 $QualifierIdOrObject = $QualifierIdOrObject->Id();
1151 # delete intersection record from database
1152 $this->DB->Query(
"DELETE FROM FieldQualifierInts WHERE QualifierId = "
1153 .$QualifierIdOrObject.
" AND MetadataFieldId = ".
1157 # retrieve item factory object for this field
1160 switch ($this->
Type())
1185 # the field should not be viewed if it is disabled
1191 $UserPrivs = $GLOBALS[
"G_User"]->Privileges();
1193 # the user can view the field if they can edit it
1194 if ($UserPrivs->IsGreaterThan($this->EditingPrivileges()))
1199 # if the user can view the field
1200 if ($UserPrivs->IsGreaterThan($this->ViewingPrivileges()))
1205 # the user can't view the field
1209 # ---- PRIVATE INTERFACE -------------------------------------------------
1214 private $ErrorStatus;
1215 private $AuthoringPrivileges;
1216 private $EditingPrivileges;
1217 private $ViewingPrivileges;
1218 private $PreviewingPrivileges;
1241 # field type DB/PHP enum translations
1315 static function Create($SchemaId, $FieldType, $FieldName,
1316 $Optional = NULL, $DefaultValue = NULL)
1318 # error out if field type is bad
1321 throw new InvalidArgumentException(
"Bad field type (".$FieldType.
").");
1324 # error out if field name is duplicate
1326 $FieldName = trim($FieldName);
1327 $DuplicateCount = $DB->Query(
1328 "SELECT COUNT(*) AS RecordCount FROM MetadataFields"
1329 .
" WHERE FieldName = '".addslashes($FieldName).
"'"
1330 .
" AND SchemaId = ".intval($SchemaId),
1332 if ($DuplicateCount > 0)
1334 throw new InvalidArgumentException(
"Duplicate field name (".$FieldName.
").");
1337 # grab current user ID
1338 $UserId = $GLOBALS[
"G_User"]->Get(
"UserId");
1340 # normalize schema ID
1342 $SchemaId = $Schema->Id();
1344 # use schema privileges as starting privilege values
1345 $AuthorPrivs = $Schema->AuthoringPrivileges();
1346 $EditPrivs = $Schema->EditingPrivileges();
1347 $ViewPrivs = $Schema->ViewingPrivileges();
1348 $PreviewPrivs = $Schema->ViewingPrivileges();
1350 # lock DB tables and get next temporary field ID
1351 $DB->Query(
"LOCK TABLES MetadataFields WRITE");
1352 $FieldId = $Schema->GetNextTempItemId();
1354 # add field to MDF table in database
1355 $DB->Query(
"INSERT INTO MetadataFields"
1356 .
" (FieldId, SchemaId, FieldName, FieldType, LastModifiedById,"
1357 .
" Optional, AuthoringPrivileges, EditingPrivileges,"
1358 .
" ViewingPrivileges, PreviewingPrivileges)"
1360 .intval($FieldId).
", "
1361 .intval($SchemaId).
","
1362 .
" '".addslashes($FieldName).
"',"
1364 .intval($UserId).
", "
1365 .($Optional ?
"1" :
"0").
","
1366 .
"'".mysql_escape_string($AuthorPrivs->Data()).
"',"
1367 .
"'".mysql_escape_string($EditPrivs->Data()).
"',"
1368 .
"'".mysql_escape_string($ViewPrivs->Data()).
"',"
1369 .
"'".mysql_escape_string($PreviewPrivs->Data()).
"')");
1372 $DB->Query(
"UNLOCK TABLES");
1377 # set field defaults
1378 $Field->SetDefaults();
1380 # set the default value if specified
1381 if ($DefaultValue !== NULL)
1383 $Field->DefaultValue($DefaultValue);
1386 # return newly-constructed field to caller
1398 # assume everything will be okay
1401 # retrieve field info from database
1403 $Result = $this->DB->Query(
"SELECT * FROM MetadataFields"
1404 .
" WHERE FieldId = ".intval($FieldId));
1405 if ($this->DB->NumRowsSelected() == 0)
1407 throw new InvalidArgumentException(
"Invalid metadata field ID ("
1410 $Row = $this->DB->FetchRow();
1411 $this->DBFields = $Row;
1412 $this->
Id = $FieldId;
1414 # if privileges have not yet been initialized
1415 if (!strlen($this->DBFields[
"AuthoringPrivileges"]))
1417 # set default values for privileges from metadata schema
1426 # set privileges from stored values
1428 $Row[
"AuthoringPrivileges"]);
1430 $Row[
"EditingPrivileges"]);
1432 $Row[
"ViewingPrivileges"]);
1434 $Row[
"PreviewingPrivileges"]);
1437 # set database column name
1438 $this->DBFields[
"DBFieldName"] =
1439 $this->NormalizeFieldNameForDB($this->DBFields[
"FieldName"]);
1448 "Description" => NULL,
1449 "Instructions" => NULL,
1453 "AllowMultiple" => FALSE,
1454 "IncludeInKeywordSearch" => FALSE,
1455 "IncludeInAdvancedSearch" => FALSE,
1456 "IncludeInFacetedSearch" => FALSE,
1457 "IncludeInSortOptions" => TRUE,
1458 "IncludeInRecommender" => FALSE,
1459 "ParagraphRows" => 4,
1460 "ParagraphCols" => 50,
1462 "FlagOnLabel" =>
"On",
1463 "FlagOffLabel" =>
"Off",
1464 "DateFormat" => NULL,
1465 "RecommenderWeight" => 1,
1468 "MaxPreviewHeight" => 100,
1469 "MaxPreviewWidth" => 100,
1470 "MaxThumbnailHeight" => 50,
1471 "MaxThumbnailWidth" => 50,
1472 "DefaultAltText" => NULL,
1473 "UsesQualifiers" => FALSE,
1474 "HasItemLevelQualifiers" => FALSE,
1475 "ShowQualifiers" => FALSE,
1476 "DefaultQualifier" => NULL,
1477 "AllowHTML" => FALSE,
1478 "UseWysiwygEditor" => FALSE,
1479 "UseForOaiSets" => FALSE,
1480 "DisplayAsListForAdvancedSearch" => FALSE,
1481 "OptionListThreshold" => 25,
1482 "AjaxThreshold" => 50,
1483 "NumAjaxResults" => 50,
1484 "PointPrecision" => 8,
1485 "PointDecimalDigits" => 5,
1486 "UserPrivilegeRestrictions" => array(),
1487 "UpdateMethod" =>
"NoAutoUpdate",
1488 # 9999 is the
default max value because
default number field length is 4
1489 "MaxValue" => 9999);
1497 "DefaultValue" => NULL,
1498 "SearchWeight" => 1,
1499 "TextFieldSize" => 50,
1500 "MaxLength" => 100),
1502 "DefaultValue" => NULL,
1503 "SearchWeight" => 1,
1504 "TextFieldSize" => 50,
1505 "MaxLength" => 100),
1507 "DefaultValue" => NULL,
1508 "SearchWeight" => 1,
1509 "TextFieldSize" => 4,
1510 "MaxLength" => 100),
1512 "DefaultValue" => NULL,
1513 "SearchWeight" => 1,
1514 "TextFieldSize" => 10,
1515 "MaxLength" => 100),
1517 "DefaultValue" => NULL,
1518 "SearchWeight" => 1,
1519 "TextFieldSize" => 50,
1520 "MaxLength" => 100),
1522 "DefaultValue" => NULL,
1523 "SearchWeight" => 1,
1524 "TextFieldSize" => 50,
1525 "MaxLength" => 100),
1527 "DefaultValue" => NULL,
1528 "SearchWeight" => 1,
1529 "TextFieldSize" => 50,
1530 "MaxLength" => 100),
1532 "DefaultValue" => NULL,
1533 "SearchWeight" => 3,
1534 "TextFieldSize" => 50,
1535 "MaxLength" => 100),
1537 "DefaultValue" => NULL,
1538 "SearchWeight" => 3,
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" => 100),
1552 "DefaultValue" => NULL,
1553 "SearchWeight" => 1,
1554 "TextFieldSize" => 50,
1555 "MaxLength" => 100),
1557 "DefaultValue" => NULL,
1558 "SearchWeight" => 1,
1559 "TextFieldSize" => 50,
1560 "MaxLength" => 255),
1562 "DefaultValue" => array(
"X" => NULL,
"Y" => NULL),
1563 "SearchWeight" => 1,
1564 "TextFieldSize" => 10,
1565 "MaxLength" => 100),
1567 "DefaultValue" => NULL,
1568 "SearchWeight" => 1,
1569 "TextFieldSize" => 50,
1570 "MaxLength" => 100));
1578 # set defaults that are the same for every field
1579 foreach (self::$FixedDefaults as $Key => $Value)
1581 $this->$Key($Value);
1584 # set defaults that depend on the type of the field
1585 foreach (self::$TypeBasedDefaults[$this->
Type()] as $Key => $Value)
1587 $this->$Key($Value);
1590 # tweak the update method if dealing with the date of record creation
1591 if ($this->
Name() ==
"Date Of Record Creation")
1597 # remove field from database (only for use by MetadataSchema object)
1600 # clear other database entries as appropriate for field type
1602 $DBFieldName = $this->DBFields[
"DBFieldName"];
1614 # remove field from resources table
1615 if ($DB->FieldExists(
"Resources", $DBFieldName))
1617 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"`");
1622 if ($DB->FieldExists(
"Resources", $DBFieldName.
"X"))
1624 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"X`");
1625 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"Y`");
1630 # remove fields from resources table
1631 if ($DB->FieldExists(
"Resources", $DBFieldName.
"Begin"))
1633 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"Begin`");
1634 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"End`");
1635 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"Precision`");
1640 $DB->Query(
"SELECT ClassificationId FROM Classifications "
1641 .
"WHERE FieldId = ".$this->
Id());
1643 while ($ClassificationId = $DB->FetchField(
"ClassificationId"))
1645 # remove any resource / name intersections
1646 $TempDB->Query(
"DELETE FROM ResourceClassInts WHERE "
1647 .
"ClassificationId = ".$ClassificationId);
1649 # remove controlled name
1650 $TempDB->Query(
"DELETE FROM Classifications WHERE "
1651 .
"ClassificationId = ".$ClassificationId);
1657 $DB->Query(
"SELECT ControlledNameId FROM ControlledNames "
1658 .
"WHERE FieldId = ".$this->
Id());
1660 while ($ControlledNameId = $DB->FetchField(
"ControlledNameId"))
1662 # remove any resource / name intersections
1663 $TempDB->Query(
"DELETE FROM ResourceNameInts WHERE "
1664 .
"ControlledNameId = ".$ControlledNameId);
1666 # remove any variant names
1667 $TempDB->Query(
"DELETE FROM VariantNames WHERE "
1668 .
"ControlledNameId = ".$ControlledNameId);
1670 # remove controlled name
1671 $TempDB->Query(
"DELETE FROM ControlledNames WHERE "
1672 .
"ControlledNameId = ".$ControlledNameId);
1677 # for each file associated with this field
1678 $DB->Query(
"SELECT FileId FROM Files WHERE FieldId = '".$this->
Id().
"'");
1679 while ($FileId = $DB->FetchRow())
1682 $File =
new File(intval($FileId));
1688 # remove any resource references for the field
1690 DELETE FROM ReferenceInts
1691 WHERE FieldId = '".addslashes($this->
Id()).
"'");
1695 # remove field from database
1696 $DB->Query(
"DELETE FROM MetadataFields "
1697 .
"WHERE FieldId = '".$this->DBFields[
"FieldId"].
"'");
1699 # remove any qualifier associations
1700 $DB->Query(
"DELETE FROM FieldQualifierInts WHERE MetadataFieldId = '"
1701 .$this->DBFields[
"FieldId"].
"'");
1703 # get the order objects the field is part of
1706 # remove it if it's a direct descendant
1707 $Order->RemoveItem($this->
Id(),
"MetadataField");
1709 # also make sure to remove it if it's part of a group
1710 foreach ($Order->GetItemIds() as $Item)
1712 if ($Item[
"Type"] ==
"MetadataFieldGroup")
1715 $Group->RemoveItem($this->
Id(),
"MetadataField");
1721 # modify any database fields
1722 private function ModifyField($NewName = NULL, $NewType = NULL)
1724 # grab old DB field name
1725 $OldDBFieldName = $this->DBFields[
"DBFieldName"];
1726 $OldFieldType = NULL;
1728 # if new field name supplied
1729 if ($NewName != NULL)
1731 # cache the old name for options and controllednames below
1732 $OldName = $this->DBFields[
"FieldName"];
1735 $this->UpdateValue(
"FieldName", $NewName);
1737 # determine new DB field name
1738 $NewDBFieldName = $this->NormalizeFieldNameForDB($NewName);
1740 # store new database field name
1741 $this->DBFields[
"DBFieldName"] = $NewDBFieldName;
1745 # set new field name equal to old field name
1746 $NewDBFieldName = $OldDBFieldName;
1749 # if new type supplied
1750 if ($NewType != NULL)
1752 # grab old field type
1755 # store new field type
1759 # if this is not a temporary field
1760 if ($this->
Id() >= 0)
1762 # modify field in DB as appropriate for field type
1770 # alter field declaration in Resources table
1771 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1772 .$OldDBFieldName.
"` `"
1773 .$NewDBFieldName.
"` TEXT "
1774 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1779 # alter field declaration in Resources table
1780 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1781 .$OldDBFieldName.
"` `"
1782 .$NewDBFieldName.
"` INT "
1783 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1787 $Precision = $this->UpdateValue(
"PointPrecision",
1789 $Digits = $this->UpdateValue(
"PointDecimalDigits",
1791 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN "
1792 .
"`".$OldDBFieldName.
"X` "
1793 .
"`".$NewDBFieldName.
"X`".
1794 " DECIMAL(".$Precision.
",".$Digits.
")");
1795 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN "
1796 .
"`".$OldDBFieldName.
"Y` "
1797 .
"`".$NewDBFieldName.
"Y`".
1798 " DECIMAL(".$Precision.
",".$Digits.
")");
1802 # if DB field name has changed
1803 if ($NewDBFieldName != $OldDBFieldName)
1805 # alter field declaration in Resources table
1806 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1807 .$OldDBFieldName.
"` `"
1808 .$NewDBFieldName.
"` TEXT");
1813 # alter field declaration in Resources table
1814 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1815 .$OldDBFieldName.
"` `"
1816 .$NewDBFieldName.
"` INT"
1819 # set any unset values to default
1820 $DB->Query(
"UPDATE Resources SET `".$NewDBFieldName
1822 .
" WHERE `".$NewDBFieldName.
"` IS NULL");
1826 # if new type supplied and new type is different from old
1827 if (($NewType != NULL) && ($NewType != $OldFieldType))
1829 # if old type was time stamp
1832 # change time stamp field in resources table to begin date
1833 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1834 .$OldDBFieldName.
"` `"
1835 .$NewDBFieldName.
"Begin` DATE "
1836 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1838 # add end date and precision fields
1839 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$NewDBFieldName.
"End"
1841 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$NewDBFieldName.
"Precision`"
1842 .
" INT ".($Optional ?
"" :
"NOT NULL"));
1844 # set precision to reflect time stamp content
1845 $DB->Query(
"UPDATE Resources SET `".$NewDBFieldName.
"Precision` = "
1850 exit(
"<br>ERROR: Attempt to convert metadata field to date from type other than timestamp<br>\n");
1855 # change name of fields
1856 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1857 .$OldDBFieldName.
"Begin` `"
1858 .$NewDBFieldName.
"Begin` DATE "
1859 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1860 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1861 .$OldDBFieldName.
"End` `"
1862 .$NewDBFieldName.
"End` DATE "
1863 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1864 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1865 .$OldDBFieldName.
"Precision` `"
1866 .$NewDBFieldName.
"Precision` INT "
1867 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1872 # if new type supplied and new type is different from old
1873 if (($NewType != NULL) && ($NewType != $OldFieldType))
1875 # if old type was date
1878 # change begin date field in resource table to time stamp
1879 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1880 .$OldDBFieldName.
"Begin` `"
1881 .$NewDBFieldName.
"` DATETIME "
1882 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1884 # drop end date and precision fields
1885 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `"
1886 .$OldDBFieldName.
"End`");
1887 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `"
1888 .$OldDBFieldName.
"Precision`");
1892 exit(
"<br>ERROR: Attempt to convert metadata field to time stamp from type other than date<br>\n");
1897 # change name of field
1898 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1899 .$OldDBFieldName.
"` `"
1900 .$NewDBFieldName.
"` DATETIME "
1901 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1913 # if qualifier DB field exists
1914 if ($DB->FieldExists(
"Resources", $OldDBFieldName.
"Qualifier"))
1916 # rename qualifier DB field
1917 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1918 .$OldDBFieldName.
"Qualifier` `"
1919 .$NewDBFieldName.
"Qualifier` INT ");
1924 # convenience functions to supply parameters to Database->UpdateValue()
1925 private function UpdateValue($FieldName, $NewValue)
1927 return $this->DB->UpdateValue(
"MetadataFields", $FieldName, $NewValue,
1928 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1931 private function UpdateIntValue($FieldName, $NewValue)
1933 return $this->DB->UpdateIntValue(
"MetadataFields", $FieldName, $NewValue,
1934 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1937 private function UpdateFloatValue($FieldName, $NewValue)
1939 return $this->DB->UpdateFloatValue(
"MetadataFields", $FieldName, $NewValue,
1940 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1943 private function UpdateBoolValue($FieldName, $NewValue)
1945 $NewValue = $this->TranslateStringToConstants($NewValue);
1946 return $this->DB->UpdateIntValue(
"MetadataFields", $FieldName, $NewValue,
1947 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1950 private function UpdateConstValue($FieldName, $NewValue, $ClassName=NULL)
1952 $NewValue = $this->TranslateStringToConstants($NewValue, $ClassName);
1953 return $this->DB->UpdateIntValue(
"MetadataFields", $FieldName, $NewValue,
1954 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1958 # normalize field name for use as database field name
1959 private function NormalizeFieldNameForDB($Name)
1961 return preg_replace(
"/[^a-z0-9]/i",
"", $Name)
1966 # add any needed database fields and/or entries
1967 private function AddDatabaseFields()
1969 # grab values for common use
1971 $FieldName = $this->
Name();
1976 # set up field(s) based on field type
1977 switch ($this->
Type())
1982 # add field to resources table (if not already present)
1983 if (!$DB->FieldExists(
"Resources", $DBFieldName))
1985 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1986 .
"` TEXT ".($Optional ?
"" :
"NOT NULL"));
1989 # if default value supplied
1990 if ($DefaultValue != NULL)
1992 # set all existing records to default value
1993 $DB->Query(
"UPDATE Resources SET `"
1994 .$DBFieldName.
"` = '".addslashes($DefaultValue).
"'");
1999 # add field to resources table (if not already present)
2000 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2002 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
2003 .
"` INT ".($Optional ?
"" :
"NOT NULL"));
2006 # if default value supplied
2007 if ($DefaultValue != NULL)
2009 # set all existing records to default value
2010 $DB->Query(
"UPDATE Resources SET `"
2011 .$DBFieldName.
"` = '".addslashes($DefaultValue).
"'");
2016 if (!$DB->FieldExists(
"Resources", $DBFieldName.
"X"))
2018 $Precision = $this->UpdateValue(
"PointPrecision",
2020 $Digits = $this->UpdateValue(
"PointDecimalDigits",
2023 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
2025 " DECIMAL(".$Precision.
",".$Digits.
")");
2026 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
2028 " DECIMAL(".$Precision.
",".$Digits.
")");
2033 # if field is not already present in database
2034 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2036 # add field to resources table
2037 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
2038 .
"` INT DEFAULT ".intval($DefaultValue));
2040 # set all existing records to default value
2041 $DB->Query(
"UPDATE Resources SET `"
2042 .$DBFieldName.
"` = ".intval($DefaultValue));
2047 # add field to resources table (if not already present)
2048 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2050 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
2051 .
"` INT ".($Optional ?
"" :
"NOT NULL"));
2056 # add fields to resources table (if not already present)
2057 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2059 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
2060 .$DBFieldName.
"` TEXT");
2065 # add fields to resources table (if not already present)
2066 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2068 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
2069 .$DBFieldName.
"` INT");
2074 # add fields to resources table (if not already present)
2075 if (!$DB->FieldExists(
"Resources", $DBFieldName.
"Begin"))
2077 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName.
"Begin`"
2078 .
" DATE ".($Optional ?
"" :
"NOT NULL"));
2080 if (!$DB->FieldExists(
"Resources", $DBFieldName.
"End"))
2082 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName.
"End`"
2085 if (!$DB->FieldExists(
"Resources", $DBFieldName.
"Precision"))
2087 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName.
"Precision`"
2088 .
" INT ".($Optional ?
"" :
"NOT NULL"));
2093 # add fields to resources table (if not already present)
2094 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2096 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
2097 .
"` DATETIME ".($Optional ?
"" :
"NOT NULL"));
2108 exit(
"<br>ERROR: Attempt to add database fields for illegal metadata field type<br>\n");
2120 private function TranslateStringToConstants($CString, $ClassName = NULL)
2122 # if not a string return value unchanged to caller
2123 if (!is_string($CString) || ($CString ===
DB_NOVALUE))
2125 $ReturnValue = $CString;
2127 # handle booleans as a special case
2128 elseif (strtoupper(trim($CString)) ==
"TRUE")
2130 $ReturnValue = TRUE;
2132 elseif (strtoupper(trim($CString)) ==
"FALSE")
2134 $ReturnValue = FALSE;
2138 # assume no values will be found
2139 $ReturnValue = NULL;
2141 # split apart any ORed-together values
2142 $Values = explode(
"|", $CString);
2144 # for each value found
2145 foreach ($Values as $Value)
2147 # trim off any extraneous whitespace
2148 $Value = trim($Value);
2150 # add class name prefix to constant name if requested
2151 if ($ClassName) { $Value = $ClassName.
"::".$Value; }
2153 # if value corresponds to a constant
2154 if (defined($Value))
2156 # add constant to return value
2157 $ReturnValue = ($ReturnValue === NULL)
2159 : ($ReturnValue | constant($Value));
2163 # if no corresponding constants were found
2164 if ($ReturnValue === NULL)
2166 # return original value to caller
2167 $ReturnValue = $CString;
2171 # return result to caller
2172 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.