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); }
569 {
return $this->UpdateConstValue(
"ViewingPrivilege", $NewValue); }
571 {
return $this->UpdateConstValue(
"AuthoringPrivilege", $NewValue); }
573 {
return $this->UpdateConstValue(
"EditingPrivilege", $NewValue); }
575 {
return $this->UpdateConstValue(
"ImagePreviewPrivilege", $NewValue); }
577 {
return $this->UpdateConstValue(
"TreeBrowsingPrivilege", $NewValue); }
579 {
return $this->UpdateBoolValue(
"EnableOnOwnerReturn", $NewValue); }
581 {
return $this->UpdateConstValue(
"ViewingUserIsValue", $NewValue,
"MetadataField"); }
583 {
return $this->UpdateConstValue(
"AuthoringUserIsValue", $NewValue,
"MetadataField"); }
585 {
return $this->UpdateConstValue(
"EditingUserIsValue", $NewValue,
"MetadataField"); }
587 {
return $this->UpdateIntValue(
"ViewingUserValue", $NewValue,
"MetadataField"); }
589 {
return $this->UpdateIntValue(
"AuthoringUserValue", $NewValue,
"MetadataField"); }
591 {
return $this->UpdateIntValue(
"EditingUserValue", $NewValue,
"MetadataField"); }
593 {
return $this->UpdateBoolValue(
"RequiredBySPT", $NewValue); }
600 $NewValue = serialize((array) $NewValue);
603 $Value = $this->UpdateValue(
"UserPrivilegeRestrictions", $NewValue);
608 $Value = (array) unserialize($Value);
611 # no value set, set it to an empty array
625 $OldValue = $this->UpdateValue(
"PointPrecision",
DB_NOVALUE);
627 if ($NewValue != $OldValue)
629 $Decimals = $this->UpdateValue(
"PointDecimalDigits",
DB_NOVALUE);
630 $TotalDigits = $NewValue + $Decimals;
632 $this->DB->Query(
"ALTER TABLE Resources MODIFY COLUMN "
633 .
"`".$this->DBFields[
"DBFieldName"].
"X` "
634 .
"DECIMAL(".$TotalDigits.
",".$Decimals.
")");
635 $this->DB->Query(
"ALTER TABLE Resources MODIFY COLUMN "
636 .
"`".$this->DBFields[
"DBFieldName"].
"Y` "
637 .
"DECIMAL(".$TotalDigits.
",".$Decimals.
")");
641 return $this->UpdateValue(
"PointPrecision", $NewValue);
649 $OldValue = $this->UpdateValue(
"PointDecimalDigits",
DB_NOVALUE);
651 if ($NewValue != $OldValue)
653 $Precision = $this->UpdateValue(
"PointPrecision",
DB_NOVALUE);
655 $TotalDigits = $NewValue + $Precision;
657 $this->DB->Query(
"ALTER TABLE Resources MODIFY COLUMN "
658 .
"`".$this->DBFields[
"DBFieldName"].
"X` "
659 .
"DECIMAL(".$TotalDigits.
",".$NewValue.
")");
660 $this->DB->Query(
"ALTER TABLE Resources MODIFY COLUMN "
661 .
"`".$this->DBFields[
"DBFieldName"].
"Y` "
662 .
"DECIMAL(".$TotalDigits.
",".$NewValue.
")");
666 return $this->UpdateValue(
"PointDecimalDigits", $NewValue);
675 isset($NewValue[
"X"]) && isset($NewValue[
"Y"]))
677 $NewValue = $NewValue[
"X"].
",".$NewValue[
"Y"];
680 # invalid value given
686 $Value = $this->UpdateValue(
"DefaultValue", $NewValue);
688 if (is_array($Value))
690 $tmp = explode(
",", $Value);
694 return array(
"X" => $tmp[0],
"Y" => $tmp[1]);
698 return array(
"X" => NULL,
"Y" => NULL);
703 # multiple default values to set
704 if (is_array($NewValue))
707 if (count($NewValue) == 0)
712 # multiple defaults are allowed
715 $NewValue = serialize($NewValue);
718 # only one default is allowed so get the first one
721 $NewValue = array_shift($NewValue);
725 $Result = $this->UpdateValue(
"DefaultValue", $NewValue);
727 return empty($Result) || is_numeric($Result) ?
728 $Result : unserialize($Result);
731 return $this->UpdateValue(
"DefaultValue", $NewValue);
741 return $this->UpdateValue(
"UpdateMethod", $NewValue);
744 # get possible values (only meaningful for Trees, Controlled Names, Options,
746 # (index for returned array is IDs for values)
749 # retrieve values based on field type
750 switch ($this->
Type())
753 $QueryString =
"SELECT ClassificationId, ClassificationName"
754 .
" FROM Classifications WHERE FieldId = ".$this->
Id()
755 .
" ORDER BY ClassificationName";
756 if ($MaxNumberOfValues)
758 $QueryString .=
" LIMIT ".intval($MaxNumberOfValues).
" OFFSET "
761 $this->DB->Query($QueryString);
762 $PossibleValues = $this->DB->FetchColumn(
763 "ClassificationName",
"ClassificationId");
768 $QueryString =
"SELECT ControlledNameId, ControlledName"
769 .
" FROM ControlledNames WHERE FieldId = ".$this->
Id()
770 .
" ORDER BY ControlledName";
771 if ($MaxNumberOfValues)
773 $QueryString .=
" LIMIT ".intval($MaxNumberOfValues).
" OFFSET "
776 $this->DB->Query($QueryString);
777 $PossibleValues = $this->DB->FetchColumn(
778 "ControlledName",
"ControlledNameId");
789 $PossibleValues = array();
791 if (count($Restrictions))
793 $PossibleValues = call_user_func_array(
794 array($UserFactory,
"GetUsersWithPrivileges"),
800 $Users = $UserFactory->GetMatchingUsers(
".*.");
802 foreach ($Users as $Id => $Data)
804 $PossibleValues[$Id] = $Data[
"UserName"];
811 # for everything else return an empty array
812 $PossibleValues = array();
816 # return array of possible values to caller
817 return $PossibleValues;
820 # get count of possible values (only meaningful for Trees, Controlled Names,
821 # Options, and Users)
824 # retrieve values based on field type
825 switch ($this->
Type())
828 $Count = $this->DB->Query(
"SELECT count(*) AS ValueCount"
829 .
" FROM Classifications WHERE FieldId = ".$this->
Id(),
835 $Count = $this->DB->Query(
"SELECT count(*) AS ValueCount"
836 .
" FROM ControlledNames WHERE FieldId = ".$this->
Id(),
849 # for everything else return an empty array
854 # return count of possible values to caller
858 # get ID for specified value (only meaningful for Trees / Controlled Names / Options)
859 # (returns NULL if value not found)
862 # retrieve ID based on field type
863 switch ($this->
Type())
866 $Id = $this->DB->Query(
"SELECT ClassificationId FROM Classifications"
867 .
" WHERE ClassificationName = '".addslashes($Value).
"'"
868 .
" AND FieldId = ".$this->
Id(),
874 $Id = $this->DB->Query(
"SELECT ControlledNameId FROM ControlledNames"
875 .
" WHERE ControlledName = '".addslashes($Value).
"'"
876 .
" AND FieldId = ".$this->
Id(),
881 # for everything else return NULL
886 # return ID for value to caller
890 # get value for specified ID (only meaningful for Trees / Controlled Names / Options)
891 # (returns NULL if ID not found)
894 # retrieve ID based on field type
895 switch ($this->
Type())
898 $Value = $this->DB->Query(
"SELECT ClassificationName FROM Classifications"
899 .
" WHERE ClassificationId = '".intval($Id).
"'"
900 .
" AND FieldId = ".$this->
Id(),
901 "ClassificationName");
906 $Value = $this->DB->Query(
"SELECT ControlledName FROM ControlledNames"
907 .
" WHERE ControlledNameId = '".intval($Id).
"'"
908 .
" AND FieldId = ".$this->
Id(),
913 # for everything else return NULL
918 # return ID for value to caller
934 # retrieve ID if object passed in
935 if (is_object($Value) && method_exists($Value,
"Id"))
937 $Value = $Value->Id();
940 # check value based on field type
941 $DBFieldName = $this->DBFields[
"DBFieldName"];
942 switch ($this->
Type())
953 $UseCount = $this->DB->Query(
"SELECT COUNT(*) AS UseCount"
955 .
" WHERE `".$DBFieldName.
"` = '".addslashes($Value).
"'"
956 .
" AND SchemaId = ".intval($this->DBFields[
"SchemaId"]),
961 $UseCount = $this->DB->Query(
"SELECT COUNT(*) AS UseCount"
962 .
" FROM ResourceClassInts"
963 .
" WHERE ClassificationId = ".intval($Value),
969 $UseCount = $this->DB->Query(
"SELECT COUNT(*) AS UseCount"
970 .
" FROM ResourceNameInts"
971 .
" WHERE ControlledNameId = ".intval($Value),
976 $UseCount = $this->DB->Query(
"SELECT COUNT(*) AS UseCount"
978 .
" WHERE `".$DBFieldName.
"X` = '".$Value[
"X"].
"'"
979 .
" AND `".$DBFieldName.
"Y` = '".$Value[
"Y"].
"'"
980 .
" AND SchemaId = ".intval($this->DBFields[
"SchemaId"]),
985 throw new Exception(__CLASS__.
"::".__METHOD__.
"() called for"
986 .
" unsupported field type (".$this->Type().
").");
990 # report use count to caller
994 # get/set whether field uses item-level qualifiers
997 # if value provided different from present value
999 && ($NewValue != $this->DBFields[
"HasItemLevelQualifiers"]))
1001 # check if qualifier column currently exists
1003 $QualColExists = $this->DB->FieldExists(
"Resources", $QualColName);
1005 # if new value indicates qualifiers should now be used
1006 if ($NewValue == TRUE)
1008 # if qualifier column does not exist in DB for this field
1009 if ($QualColExists == FALSE)
1011 # add qualifier column in DB for this field
1012 $this->DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
1013 .$QualColName.
"` INT");
1018 # if qualifier column exists in DB for this field
1019 if ($QualColExists == TRUE)
1021 # remove qualifier column from DB for this field
1022 $this->DB->Query(
"ALTER TABLE Resources DROP COLUMN `"
1028 return $this->UpdateValue(
"HasItemLevelQualifiers", $NewValue);
1031 # get list of qualifiers associated with field
1034 # start with empty list
1037 # for each associated qualifier
1038 $this->DB->Query(
"SELECT QualifierId FROM FieldQualifierInts"
1039 .
" WHERE MetadataFieldId = ".$this->DBFields[
"FieldId"]);
1040 while ($Record = $this->DB->FetchRow())
1042 # load qualifier object
1043 $Qual =
new Qualifier($Record[
"QualifierId"]);
1045 # add qualifier ID and name to list
1046 $List[$Qual->Id()] = $Qual->Name();
1049 # return list to caller
1053 # get list of qualifiers not associated with field
1056 # grab list of associated qualifiers
1059 # get list of all qualifiers
1061 $AllQualifiers = $QFactory->GetItemNames();
1063 # return list of unassociated qualifiers
1064 return array_diff($AllQualifiers, $AssociatedQualifiers);
1073 # if qualifier object passed in
1074 if (is_object($Qualifier))
1076 # grab qualifier ID from object
1077 $Qualifier = $Qualifier->Id();
1079 # else if string passed in does not look like ID
1080 elseif (!preg_match(
'/^[0-9]+$/', $Qualifier))
1082 # assume string passed in is name and use it to retrieve ID
1084 $Qualifier = $QFact->GetItemIdByName($Qualifier);
1087 # if not already associated
1088 $RecordCount = $this->DB->Query(
1089 "SELECT COUNT(*) AS RecordCount FROM FieldQualifierInts"
1090 .
" WHERE QualifierId = ".$Qualifier
1091 .
" AND MetadataFieldId = ".$this->
Id(),
"RecordCount");
1092 if ($RecordCount < 1)
1094 # associate field with qualifier
1095 $this->DB->Query(
"INSERT INTO FieldQualifierInts SET"
1096 .
" QualifierId = ".$Qualifier.
","
1097 .
" MetadataFieldId = ".$this->Id());
1108 # delete qualifier association
1111 # if qualifier object passed in
1112 if (is_object($QualifierIdOrObject))
1114 # grab qualifier ID from object
1115 $QualifierIdOrObject = $QualifierIdOrObject->Id();
1118 # delete intersection record from database
1119 $this->DB->Query(
"DELETE FROM FieldQualifierInts WHERE QualifierId = "
1120 .$QualifierIdOrObject.
" AND MetadataFieldId = ".
1124 # retrieve item factory object for this field
1127 switch ($this->
Type())
1152 # the field should not be viewed if it is disabled
1158 $UserPrivs = $GLOBALS[
"G_User"]->Privileges();
1160 # the user can view the field if they can edit it
1161 if ($UserPrivs->IsGreaterThan($this->EditingPrivileges()))
1166 # if the user can view the field
1167 if ($UserPrivs->IsGreaterThan($this->ViewingPrivileges()))
1172 # the user can't view the field
1176 # ---- PRIVATE INTERFACE -------------------------------------------------
1181 private $ErrorStatus;
1182 private $AuthoringPrivileges;
1183 private $EditingPrivileges;
1184 private $ViewingPrivileges;
1185 private $PreviewingPrivileges;
1208 # field type DB/PHP enum translations
1282 static function Create($SchemaId, $FieldType, $FieldName,
1283 $Optional = NULL, $DefaultValue = NULL)
1285 # error out if field type is bad
1288 throw new InvalidArgumentException(
"Bad field type (".$FieldType.
").");
1291 # error out if field name is duplicate
1293 $FieldName = trim($FieldName);
1294 $DuplicateCount = $DB->Query(
1295 "SELECT COUNT(*) AS RecordCount FROM MetadataFields"
1296 .
" WHERE FieldName = '".addslashes($FieldName).
"'"
1297 .
" AND SchemaId = ".intval($SchemaId),
1299 if ($DuplicateCount > 0)
1301 throw new InvalidArgumentException(
"Duplicate field name (".$FieldName.
").");
1304 # grab current user ID
1305 $UserId = $GLOBALS[
"G_User"]->Get(
"UserId");
1307 # normalize schema ID
1309 $SchemaId = $Schema->Id();
1311 # use schema privileges as starting privilege values
1312 $AuthorPrivs = $Schema->AuthoringPrivileges();
1313 $EditPrivs = $Schema->EditingPrivileges();
1314 $ViewPrivs = $Schema->ViewingPrivileges();
1315 $PreviewPrivs = $Schema->ViewingPrivileges();
1317 # lock DB tables and get next temporary field ID
1318 $DB->Query(
"LOCK TABLES MetadataFields WRITE");
1319 $FieldId = $Schema->GetNextTempItemId();
1321 # add field to MDF table in database
1322 $DB->Query(
"INSERT INTO MetadataFields"
1323 .
" (FieldId, SchemaId, FieldName, FieldType, LastModifiedById,"
1324 .
" Optional, AuthoringPrivileges, EditingPrivileges,"
1325 .
" ViewingPrivileges, PreviewingPrivileges)"
1327 .intval($FieldId).
", "
1328 .intval($SchemaId).
","
1329 .
" '".addslashes($FieldName).
"',"
1331 .intval($UserId).
", "
1332 .($Optional ?
"1" :
"0").
","
1333 .
"'".mysql_escape_string($AuthorPrivs->Data()).
"',"
1334 .
"'".mysql_escape_string($EditPrivs->Data()).
"',"
1335 .
"'".mysql_escape_string($ViewPrivs->Data()).
"',"
1336 .
"'".mysql_escape_string($PreviewPrivs->Data()).
"')");
1339 $DB->Query(
"UNLOCK TABLES");
1344 # set field defaults
1345 $Field->SetDefaults();
1347 # set the default value if specified
1348 if ($DefaultValue !== NULL)
1350 $Field->DefaultValue($DefaultValue);
1353 # return newly-constructed field to caller
1365 # assume everything will be okay
1368 # retrieve field info from database
1370 $Result = $this->DB->Query(
"SELECT * FROM MetadataFields"
1371 .
" WHERE FieldId = ".intval($FieldId));
1372 if ($this->DB->NumRowsSelected() == 0)
1374 throw new InvalidArgumentException(
"Invalid metadata field ID ("
1377 $Row = $this->DB->FetchRow();
1378 $this->DBFields = $Row;
1379 $this->
Id = $FieldId;
1381 # if privileges have not yet been initialized
1382 if (!strlen($this->DBFields[
"AuthoringPrivileges"]))
1384 # set default values for privileges from metadata schema
1393 # set privileges from stored values
1395 $Row[
"AuthoringPrivileges"]);
1397 $Row[
"EditingPrivileges"]);
1399 $Row[
"ViewingPrivileges"]);
1401 $Row[
"PreviewingPrivileges"]);
1404 # set database column name
1405 $this->DBFields[
"DBFieldName"] =
1406 $this->NormalizeFieldNameForDB($this->DBFields[
"FieldName"]);
1415 "Description" => NULL,
1416 "Instructions" => NULL,
1420 "AllowMultiple" => FALSE,
1421 "IncludeInKeywordSearch" => FALSE,
1422 "IncludeInAdvancedSearch" => FALSE,
1423 "IncludeInFacetedSearch" => FALSE,
1424 "IncludeInSortOptions" => TRUE,
1425 "IncludeInRecommender" => FALSE,
1426 "ParagraphRows" => 4,
1427 "ParagraphCols" => 50,
1429 "FlagOnLabel" =>
"On",
1430 "FlagOffLabel" =>
"Off",
1431 "DateFormat" => NULL,
1432 "RecommenderWeight" => 1,
1435 "MaxPreviewHeight" => 100,
1436 "MaxPreviewWidth" => 100,
1437 "MaxThumbnailHeight" => 50,
1438 "MaxThumbnailWidth" => 50,
1439 "DefaultAltText" => NULL,
1440 "UsesQualifiers" => FALSE,
1441 "HasItemLevelQualifiers" => FALSE,
1442 "ShowQualifiers" => FALSE,
1443 "DefaultQualifier" => NULL,
1444 "AllowHTML" => FALSE,
1445 "UseWysiwygEditor" => FALSE,
1446 "UseForOaiSets" => FALSE,
1447 "OptionListThreshold" => 25,
1448 "AjaxThreshold" => 50,
1449 "NumAjaxResults" => 50,
1450 "ViewingPrivilege" => NULL,
1451 "AuthoringPrivilege" => PRIV_MYRESOURCEADMIN,
1452 "EditingPrivilege" => PRIV_RESOURCEADMIN,
1453 "ImagePreviewPrivilege" => NULL,
1454 "TreeBrowsingPrivilege" => NULL,
1455 "ViewingUserIsValue" => self::USERISVALUE_UNSET,
1456 "AuthoringUserIsValue" => self::USERISVALUE_UNSET,
1457 "EditingUserIsValue" => self::USERISVALUE_UNSET,
1458 "ViewingUserValue" => NULL,
1459 "AuthoringUserValue" => NULL,
1460 "EditingUserValue" => NULL,
1461 "PointPrecision" => 8,
1462 "PointDecimalDigits" => 5,
1463 "UserPrivilegeRestrictions" => array(),
1464 "UpdateMethod" =>
"NoAutoUpdate",
1465 # 9999 is the
default max value because
default number field length is 4
1466 "MaxValue" => 9999);
1474 "DefaultValue" => NULL,
1475 "SearchWeight" => 1,
1476 "TextFieldSize" => 50,
1477 "MaxLength" => 100),
1479 "DefaultValue" => NULL,
1480 "SearchWeight" => 1,
1481 "TextFieldSize" => 50,
1482 "MaxLength" => 100),
1484 "DefaultValue" => NULL,
1485 "SearchWeight" => 1,
1486 "TextFieldSize" => 4,
1487 "MaxLength" => 100),
1489 "DefaultValue" => NULL,
1490 "SearchWeight" => 1,
1491 "TextFieldSize" => 10,
1492 "MaxLength" => 100),
1494 "DefaultValue" => NULL,
1495 "SearchWeight" => 1,
1496 "TextFieldSize" => 50,
1497 "MaxLength" => 100),
1499 "DefaultValue" => NULL,
1500 "SearchWeight" => 1,
1501 "TextFieldSize" => 50,
1502 "MaxLength" => 100),
1504 "DefaultValue" => NULL,
1505 "SearchWeight" => 1,
1506 "TextFieldSize" => 50,
1507 "MaxLength" => 100),
1509 "DefaultValue" => NULL,
1510 "SearchWeight" => 3,
1511 "TextFieldSize" => 50,
1512 "MaxLength" => 100),
1514 "DefaultValue" => NULL,
1515 "SearchWeight" => 3,
1516 "TextFieldSize" => 50,
1517 "MaxLength" => 100),
1519 "DefaultValue" => NULL,
1520 "SearchWeight" => 1,
1521 "TextFieldSize" => 50,
1522 "MaxLength" => 100),
1524 "DefaultValue" => NULL,
1525 "SearchWeight" => 1,
1526 "TextFieldSize" => 50,
1527 "MaxLength" => 100),
1529 "DefaultValue" => NULL,
1530 "SearchWeight" => 1,
1531 "TextFieldSize" => 50,
1532 "MaxLength" => 100),
1534 "DefaultValue" => NULL,
1535 "SearchWeight" => 1,
1536 "TextFieldSize" => 50,
1537 "MaxLength" => 255),
1539 "DefaultValue" => array(
"X" => NULL,
"Y" => NULL),
1540 "SearchWeight" => 1,
1541 "TextFieldSize" => 10,
1542 "MaxLength" => 100),
1544 "DefaultValue" => NULL,
1545 "SearchWeight" => 1,
1546 "TextFieldSize" => 50,
1547 "MaxLength" => 100));
1555 # set defaults that are the same for every field
1556 foreach (self::$FixedDefaults as $Key => $Value)
1558 $this->$Key($Value);
1561 # set defaults that depend on the type of the field
1562 foreach (self::$TypeBasedDefaults[$this->
Type()] as $Key => $Value)
1564 $this->$Key($Value);
1567 # tweak the update method if dealing with the date of record creation
1568 if ($this->
Name() ==
"Date Of Record Creation")
1574 # remove field from database (only for use by MetadataSchema object)
1577 # clear other database entries as appropriate for field type
1579 $DBFieldName = $this->DBFields[
"DBFieldName"];
1591 # remove field from resources table
1592 if ($DB->FieldExists(
"Resources", $DBFieldName))
1594 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"`");
1599 if ($DB->FieldExists(
"Resources", $DBFieldName.
"X"))
1601 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"X`");
1602 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"Y`");
1607 # remove fields from resources table
1608 if ($DB->FieldExists(
"Resources", $DBFieldName.
"Begin"))
1610 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"Begin`");
1611 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"End`");
1612 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `".$DBFieldName.
"Precision`");
1617 $DB->Query(
"SELECT ClassificationId FROM Classifications "
1618 .
"WHERE FieldId = ".$this->
Id());
1620 while ($ClassificationId = $DB->FetchField(
"ClassificationId"))
1622 # remove any resource / name intersections
1623 $TempDB->Query(
"DELETE FROM ResourceClassInts WHERE "
1624 .
"ClassificationId = ".$ClassificationId);
1626 # remove controlled name
1627 $TempDB->Query(
"DELETE FROM Classifications WHERE "
1628 .
"ClassificationId = ".$ClassificationId);
1634 $DB->Query(
"SELECT ControlledNameId FROM ControlledNames "
1635 .
"WHERE FieldId = ".$this->
Id());
1637 while ($ControlledNameId = $DB->FetchField(
"ControlledNameId"))
1639 # remove any resource / name intersections
1640 $TempDB->Query(
"DELETE FROM ResourceNameInts WHERE "
1641 .
"ControlledNameId = ".$ControlledNameId);
1643 # remove any variant names
1644 $TempDB->Query(
"DELETE FROM VariantNames WHERE "
1645 .
"ControlledNameId = ".$ControlledNameId);
1647 # remove controlled name
1648 $TempDB->Query(
"DELETE FROM ControlledNames WHERE "
1649 .
"ControlledNameId = ".$ControlledNameId);
1654 # for each file associated with this field
1655 $DB->Query(
"SELECT FileId FROM Files WHERE FieldId = '".$this->
Id().
"'");
1656 while ($FileId = $DB->FetchRow())
1659 $File =
new File(intval($FileId));
1665 # remove any resource references for the field
1667 DELETE FROM ReferenceInts
1668 WHERE FieldId = '".addslashes($this->
Id()).
"'");
1672 # remove field from database
1673 $DB->Query(
"DELETE FROM MetadataFields "
1674 .
"WHERE FieldId = '".$this->DBFields[
"FieldId"].
"'");
1676 # remove any qualifier associations
1677 $DB->Query(
"DELETE FROM FieldQualifierInts WHERE MetadataFieldId = '"
1678 .$this->DBFields[
"FieldId"].
"'");
1680 # get the order objects the field is part of
1683 # remove it if it's a direct descendant
1684 $Order->RemoveItem($this->
Id(),
"MetadataField");
1686 # also make sure to remove it if it's part of a group
1687 foreach ($Order->GetItemIds() as $Item)
1689 if ($Item[
"Type"] ==
"MetadataFieldGroup")
1692 $Group->RemoveItem($this->
Id(),
"MetadataField");
1698 # modify any database fields
1699 private function ModifyField($NewName = NULL, $NewType = NULL)
1701 # grab old DB field name
1702 $OldDBFieldName = $this->DBFields[
"DBFieldName"];
1703 $OldFieldType = NULL;
1705 # if new field name supplied
1706 if ($NewName != NULL)
1708 # cache the old name for options and controllednames below
1709 $OldName = $this->DBFields[
"FieldName"];
1712 $this->UpdateValue(
"FieldName", $NewName);
1714 # determine new DB field name
1715 $NewDBFieldName = $this->NormalizeFieldNameForDB($NewName);
1717 # store new database field name
1718 $this->DBFields[
"DBFieldName"] = $NewDBFieldName;
1722 # set new field name equal to old field name
1723 $NewDBFieldName = $OldDBFieldName;
1726 # if new type supplied
1727 if ($NewType != NULL)
1729 # grab old field type
1732 # store new field type
1736 # if this is not a temporary field
1737 if ($this->
Id() >= 0)
1739 # modify field in DB as appropriate for field type
1747 # alter field declaration in Resources table
1748 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1749 .$OldDBFieldName.
"` `"
1750 .$NewDBFieldName.
"` TEXT "
1751 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1756 # alter field declaration in Resources table
1757 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1758 .$OldDBFieldName.
"` `"
1759 .$NewDBFieldName.
"` INT "
1760 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1764 $Precision = $this->UpdateValue(
"PointPrecision",
1766 $Digits = $this->UpdateValue(
"PointDecimalDigits",
1768 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN "
1769 .
"`".$OldDBFieldName.
"X` "
1770 .
"`".$NewDBFieldName.
"X`".
1771 " DECIMAL(".$Precision.
",".$Digits.
")");
1772 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN "
1773 .
"`".$OldDBFieldName.
"Y` "
1774 .
"`".$NewDBFieldName.
"Y`".
1775 " DECIMAL(".$Precision.
",".$Digits.
")");
1779 # if DB field name has changed
1780 if ($NewDBFieldName != $OldDBFieldName)
1782 # alter field declaration in Resources table
1783 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1784 .$OldDBFieldName.
"` `"
1785 .$NewDBFieldName.
"` TEXT");
1790 # alter field declaration in Resources table
1791 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1792 .$OldDBFieldName.
"` `"
1793 .$NewDBFieldName.
"` INT"
1796 # set any unset values to default
1797 $DB->Query(
"UPDATE Resources SET `".$NewDBFieldName
1799 .
" WHERE `".$NewDBFieldName.
"` IS NULL");
1803 # if new type supplied and new type is different from old
1804 if (($NewType != NULL) && ($NewType != $OldFieldType))
1806 # if old type was time stamp
1809 # change time stamp field in resources table to begin date
1810 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1811 .$OldDBFieldName.
"` `"
1812 .$NewDBFieldName.
"Begin` DATE "
1813 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1815 # add end date and precision fields
1816 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$NewDBFieldName.
"End"
1818 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$NewDBFieldName.
"Precision`"
1819 .
" INT ".($Optional ?
"" :
"NOT NULL"));
1821 # set precision to reflect time stamp content
1822 $DB->Query(
"UPDATE Resources SET `".$NewDBFieldName.
"Precision` = "
1827 exit(
"<br>ERROR: Attempt to convert metadata field to date from type other than timestamp<br>\n");
1832 # change name of fields
1833 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1834 .$OldDBFieldName.
"Begin` `"
1835 .$NewDBFieldName.
"Begin` DATE "
1836 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1837 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1838 .$OldDBFieldName.
"End` `"
1839 .$NewDBFieldName.
"End` DATE "
1840 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1841 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1842 .$OldDBFieldName.
"Precision` `"
1843 .$NewDBFieldName.
"Precision` INT "
1844 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1849 # if new type supplied and new type is different from old
1850 if (($NewType != NULL) && ($NewType != $OldFieldType))
1852 # if old type was date
1855 # change begin date field in resource table to time stamp
1856 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1857 .$OldDBFieldName.
"Begin` `"
1858 .$NewDBFieldName.
"` DATETIME "
1859 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1861 # drop end date and precision fields
1862 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `"
1863 .$OldDBFieldName.
"End`");
1864 $DB->Query(
"ALTER TABLE Resources DROP COLUMN `"
1865 .$OldDBFieldName.
"Precision`");
1869 exit(
"<br>ERROR: Attempt to convert metadata field to time stamp from type other than date<br>\n");
1874 # change name of field
1875 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1876 .$OldDBFieldName.
"` `"
1877 .$NewDBFieldName.
"` DATETIME "
1878 .($this->DBFields[
"Optional"] ?
"" :
"NOT NULL"));
1890 # if qualifier DB field exists
1891 if ($DB->FieldExists(
"Resources", $OldDBFieldName.
"Qualifier"))
1893 # rename qualifier DB field
1894 $DB->Query(
"ALTER TABLE Resources CHANGE COLUMN `"
1895 .$OldDBFieldName.
"Qualifier` `"
1896 .$NewDBFieldName.
"Qualifier` INT ");
1901 # convenience functions to supply parameters to Database->UpdateValue()
1902 private function UpdateValue($FieldName, $NewValue)
1904 return $this->DB->UpdateValue(
"MetadataFields", $FieldName, $NewValue,
1905 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1908 private function UpdateIntValue($FieldName, $NewValue)
1910 return $this->DB->UpdateIntValue(
"MetadataFields", $FieldName, $NewValue,
1911 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1914 private function UpdateFloatValue($FieldName, $NewValue)
1916 return $this->DB->UpdateFloatValue(
"MetadataFields", $FieldName, $NewValue,
1917 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1920 private function UpdateBoolValue($FieldName, $NewValue)
1922 $NewValue = $this->TranslateStringToConstants($NewValue);
1923 return $this->DB->UpdateIntValue(
"MetadataFields", $FieldName, $NewValue,
1924 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1927 private function UpdateConstValue($FieldName, $NewValue, $ClassName=NULL)
1929 $NewValue = $this->TranslateStringToConstants($NewValue, $ClassName);
1930 return $this->DB->UpdateIntValue(
"MetadataFields", $FieldName, $NewValue,
1931 "FieldId = ".intval($this->DBFields[
"FieldId"]),
1935 # normalize field name for use as database field name
1936 private function NormalizeFieldNameForDB($Name)
1938 return preg_replace(
"/[^a-z0-9]/i",
"", $Name)
1943 # add any needed database fields and/or entries
1944 private function AddDatabaseFields()
1946 # grab values for common use
1948 $FieldName = $this->
Name();
1953 # set up field(s) based on field type
1954 switch ($this->
Type())
1959 # add field to resources table (if not already present)
1960 if (!$DB->FieldExists(
"Resources", $DBFieldName))
1962 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1963 .
"` TEXT ".($Optional ?
"" :
"NOT NULL"));
1966 # if default value supplied
1967 if ($DefaultValue != NULL)
1969 # set all existing records to default value
1970 $DB->Query(
"UPDATE Resources SET `"
1971 .$DBFieldName.
"` = '".addslashes($DefaultValue).
"'");
1976 # add field to resources table (if not already present)
1977 if (!$DB->FieldExists(
"Resources", $DBFieldName))
1979 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1980 .
"` INT ".($Optional ?
"" :
"NOT NULL"));
1983 # if default value supplied
1984 if ($DefaultValue != NULL)
1986 # set all existing records to default value
1987 $DB->Query(
"UPDATE Resources SET `"
1988 .$DBFieldName.
"` = '".addslashes($DefaultValue).
"'");
1993 if (!$DB->FieldExists(
"Resources", $DBFieldName.
"X"))
1995 $Precision = $this->UpdateValue(
"PointPrecision",
1997 $Digits = $this->UpdateValue(
"PointDecimalDigits",
2000 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
2002 " DECIMAL(".$Precision.
",".$Digits.
")");
2003 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
2005 " DECIMAL(".$Precision.
",".$Digits.
")");
2010 # if field is not already present in database
2011 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2013 # add field to resources table
2014 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
2015 .
"` INT DEFAULT ".intval($DefaultValue));
2017 # set all existing records to default value
2018 $DB->Query(
"UPDATE Resources SET `"
2019 .$DBFieldName.
"` = ".intval($DefaultValue));
2024 # add field to resources table (if not already present)
2025 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2027 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
2028 .
"` INT ".($Optional ?
"" :
"NOT NULL"));
2033 # add fields to resources table (if not already present)
2034 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2036 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
2037 .$DBFieldName.
"` TEXT");
2042 # add fields to resources table (if not already present)
2043 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2045 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `"
2046 .$DBFieldName.
"` INT");
2051 # add fields to resources table (if not already present)
2052 if (!$DB->FieldExists(
"Resources", $DBFieldName.
"Begin"))
2054 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName.
"Begin`"
2055 .
" DATE ".($Optional ?
"" :
"NOT NULL"));
2057 if (!$DB->FieldExists(
"Resources", $DBFieldName.
"End"))
2059 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName.
"End`"
2062 if (!$DB->FieldExists(
"Resources", $DBFieldName.
"Precision"))
2064 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName.
"Precision`"
2065 .
" INT ".($Optional ?
"" :
"NOT NULL"));
2070 # add fields to resources table (if not already present)
2071 if (!$DB->FieldExists(
"Resources", $DBFieldName))
2073 $DB->Query(
"ALTER TABLE Resources ADD COLUMN `".$DBFieldName
2074 .
"` DATETIME ".($Optional ?
"" :
"NOT NULL"));
2085 exit(
"<br>ERROR: Attempt to add database fields for illegal metadata field type<br>\n");
2097 private function TranslateStringToConstants($CString, $ClassName = NULL)
2099 # if not a string return value unchanged to caller
2100 if (!is_string($CString) || ($CString ===
DB_NOVALUE))
2102 $ReturnValue = $CString;
2104 # handle booleans as a special case
2105 elseif (strtoupper(trim($CString)) ==
"TRUE")
2107 $ReturnValue = TRUE;
2109 elseif (strtoupper(trim($CString)) ==
"FALSE")
2111 $ReturnValue = FALSE;
2115 # assume no values will be found
2116 $ReturnValue = NULL;
2118 # split apart any ORed-together values
2119 $Values = explode(
"|", $CString);
2121 # for each value found
2122 foreach ($Values as $Value)
2124 # trim off any extraneous whitespace
2125 $Value = trim($Value);
2127 # add class name prefix to constant name if requested
2128 if ($ClassName) { $Value = $ClassName.
"::".$Value; }
2130 # if value corresponds to a constant
2131 if (defined($Value))
2133 # add constant to return value
2134 $ReturnValue = ($ReturnValue === NULL)
2136 : ($ReturnValue | constant($Value));
2140 # if no corresponding constants were found
2141 if ($ReturnValue === NULL)
2143 # return original value to caller
2144 $ReturnValue = $CString;
2148 # return result to caller
2149 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.