00001 <?PHP
00002 #
00003 # FILE: MetadataField.php
00004 #
00005 # Part of the Collection Workflow Integration System (CWIS)
00006 # Copyright 2012 Edward Almasy and Internet Scout
00007 # http://scout.wisc.edu
00008 #
00009
00010 class MetadataField {
00011
00012 # ---- PUBLIC INTERFACE --------------------------------------------------
00013
00014 # Update methods for timestamp fields
00015 const UPDATEMETHOD_NOAUTOUPDATE = "NoAutoUpdate";
00016 const UPDATEMETHOD_ONRECORDCREATE = "OnRecordCreate";
00017 const UPDATEMETHOD_BUTTON = "Button";
00018 const UPDATEMETHOD_ONRECORDEDIT = "OnRecordEdit";
00019 const UPDATEMETHOD_ONRECORDCHANGE = "OnRecordChange";
00020
00021 # values for the *UserIsValue fields
00022 const USERISVALUE_OR = -1;
00023 const USERISVALUE_UNSET = 0;
00024 const USERISVALUE_AND = 1;
00025
00026 # get current error status of object
00027 function Status() { return $this->ErrorStatus; }
00028
00029 # get/set type of field as enumerated value
00030 function Type($NewValue = DB_NOVALUE)
00031 {
00032 # if new value supplied
00033 if (($NewValue != DB_NOVALUE)
00034 && ($NewValue != MetadataField::$FieldTypePHPEnums[
00035 $this->DBFields["FieldType"]]))
00036 {
00037 # update database fields and store new type
00038 $this->ModifyField(NULL, $NewValue);
00039 }
00040
00041 # return type to caller
00042 return MetadataField::$FieldTypePHPEnums[$this->DBFields["FieldType"]];
00043 }
00044
00045 # get type of field as type name (string)
00046 function TypeAsName()
00047 {
00048 return $this->DBFields["FieldType"];
00049 }
00050
00051 # get displayable name for the field
00052 # first tries to get label but uses field name if label isn't set
00053 function GetDisplayName()
00054 {
00055 return strlen($this->Label()) ? $this->Label() : $this->Name();
00056 }
00057
00058 # get/set name of field
00059 # once the name is set to a valid value, it cannot be changed
00060 function Name($NewName = DB_NOVALUE)
00061 {
00062 # if new name specified
00063 if ($NewName != DB_NOVALUE
00064 && trim($NewName) != $this->DBFields["FieldName"])
00065 {
00066 # if field name is invalid
00067 $NewName = trim($NewName);
00068 if (!preg_match("/^[[:alnum:] \(\)]+$/", $NewName))
00069 {
00070 # set error status to indicate illegal name
00071 $this->ErrorStatus = MetadataSchema::MDFSTAT_ILLEGALNAME;
00072 }
00073 else
00074 {
00075 # check for duplicate name
00076 $DuplicateCount = $this->DB->Query("
00077 SELECT COUNT(*) AS RecordCount FROM MetadataFields
00078 WHERE FieldName = '".addslashes($NewName)."'",
00079 "RecordCount");
00080
00081 # if field name is duplicate
00082 if ($DuplicateCount > 0)
00083 {
00084 # set error status to indicate duplicate name
00085 $this->ErrorStatus = MetadataSchema::MDFSTAT_DUPLICATENAME;
00086 }
00087 else
00088 {
00089 # modify database declaration to reflect new field name
00090 $this->ErrorStatus = MetadataSchema::MDFSTAT_OK;
00091 $this->ModifyField($NewName);
00092 }
00093 }
00094 }
00095
00096 # return value to caller
00097 return $this->DBFields["FieldName"];
00098 }
00099
00100 # get/set label of field
00101 public function Label($NewLabel = DB_NOVALUE)
00102 {
00103 $ValidValueExp = '/^[[:alnum:] ]*$/';
00104 $Value = $this->DBFields["Label"];
00105
00106 # if a new label was specified
00107 if ($NewLabel !== DB_NOVALUE && trim($NewLabel) != $Value)
00108 {
00109 $NewLabel = trim($NewLabel);
00110
00111 # if field label is invalid
00112 if (!preg_match($ValidValueExp, $NewLabel))
00113 {
00114 $this->ErrorStatus = MetadataSchema::MDFSTAT_ILLEGALLABEL;
00115 }
00116
00117 else
00118 {
00119 if (strlen($NewLabel) > 0)
00120 {
00121 $this->ErrorStatus = MetadataSchema::MDFSTAT_OK;
00122 $this->UpdateValue("Label", $NewLabel);
00123 $Value = $NewLabel;
00124 }
00125
00126 else
00127 {
00128 $this->ErrorStatus = MetadataSchema::MDFSTAT_OK;
00129 $this->UpdateValue("Label", $NewLabel);
00130 $Value = $NewLabel;
00131 }
00132 }
00133 }
00134
00135 return $Value;
00136 }
00137
00138 # get associative array (enumeration => string) containing field types we can convert to
00139 function GetAllowedConversionTypes()
00140 {
00141 # determine type list based on our type
00142 switch ($this->Type())
00143 {
00144 case MetadataSchema::MDFTYPE_TEXT:
00145 case MetadataSchema::MDFTYPE_PARAGRAPH:
00146 case MetadataSchema::MDFTYPE_NUMBER:
00147 case MetadataSchema::MDFTYPE_FLAG:
00148 case MetadataSchema::MDFTYPE_URL:
00149 $AllowedTypes = array(
00150 MetadataSchema::MDFTYPE_TEXT => "Text",
00151 MetadataSchema::MDFTYPE_PARAGRAPH => "Paragraph",
00152 MetadataSchema::MDFTYPE_NUMBER => "Number",
00153 MetadataSchema::MDFTYPE_FLAG => "Flag",
00154 MetadataSchema::MDFTYPE_URL => "Url"
00155 );
00156 break;
00157
00158 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
00159 case MetadataSchema::MDFTYPE_OPTION:
00160 $AllowedTypes = array(
00161 MetadataSchema::MDFTYPE_CONTROLLEDNAME => "ControlledName",
00162 MetadataSchema::MDFTYPE_OPTION => "Option",
00163 );
00164 break;
00165
00166 case MetadataSchema::MDFTYPE_DATE:
00167 $AllowedTypes = array(
00168 MetadataSchema::MDFTYPE_TEXT => "Text",
00169 MetadataSchema::MDFTYPE_DATE => "Date",
00170 );
00171 break;
00172
00173 case MetadataSchema::MDFTYPE_IMAGE:
00174 $AllowedTypes = array(
00175 MetadataSchema::MDFTYPE_TEXT => "Text",
00176 MetadataSchema::MDFTYPE_IMAGE => "Still Image",
00177 );
00178 break;
00179
00180 case MetadataSchema::MDFTYPE_TIMESTAMP:
00181 case MetadataSchema::MDFTYPE_TREE:
00182 case MetadataSchema::MDFTYPE_USER:
00183 case MetadataSchema::MDFTYPE_FILE:
00184 default:
00185 $AllowedTypes = array();
00186 break;
00187 }
00188
00189 # return type list to caller
00190 return $AllowedTypes;
00191 }
00192
00193 # get/set whether item is temporary instance
00194 function IsTempItem($NewSetting = NULL)
00195 {
00196 $ItemTableName = "MetadataFields";
00197 $ItemIdFieldName = "FieldId";
00198 $ItemFactoryObjectName = "MetadataSchema";
00199 $ItemAssociationTables = array(
00200 "FieldQualifierInts",
00201 );
00202 $ItemAssociationFieldName = "MetadataFieldId";
00203
00204 # if new temp item setting supplied
00205 if (!is_null($NewSetting))
00206 {
00207 # if caller requested to switch
00208 if (($this->Id() < 0 && $NewSetting == FALSE)
00209 || ($this->Id() >= 0 && $NewSetting == TRUE))
00210 {
00211 # if field name is invalid
00212 if (strlen($this->NormalizeFieldNameForDB($this->Name())) < 1)
00213 {
00214 # set error status to indicate illegal name
00215 $this->ErrorStatus = MetadataSchema::MDFSTAT_ILLEGALNAME;
00216 }
00217 else
00218 {
00219 # lock DB tables to prevent next ID from being grabbed
00220 $DB = $this->DB;
00221 $DB->Query("LOCK TABLES ".$ItemTableName." WRITE,".
00222 "APSessions WRITE, APSessionData WRITE");
00223
00224 # get next temp item ID
00225 $OldItemId = $this->Id();
00226 $Factory = new $ItemFactoryObjectName();
00227 if ($NewSetting == TRUE)
00228 {
00229 $NewId = $Factory->GetNextTempItemId();
00230 }
00231 else
00232 {
00233 $NewId = $Factory->GetNextItemId();
00234 }
00235
00236 # change item ID
00237 $DB->Query("UPDATE ".$ItemTableName." SET ".$ItemIdFieldName." = ".
00238 $NewId. " WHERE ".$ItemIdFieldName." = ".$OldItemId);
00239
00240 # release DB tables
00241 $DB->Query("UNLOCK TABLES");
00242
00243 # change associations
00244 foreach ($ItemAssociationTables as $TableName)
00245 {
00246 $DB->Query("UPDATE ".$TableName." SET ".$ItemAssociationFieldName." = ".
00247 $NewId. " WHERE ".$ItemAssociationFieldName." = ".$OldItemId);
00248 }
00249
00250 # if changing item from temp to non-temp
00251 if ($NewSetting == FALSE)
00252 {
00253 # add any needed database fields and/or entries
00254 $this->AddDatabaseFields();
00255 }
00256
00257 # update metadata field id
00258 $this->DBFields["FieldId"] = $NewId;
00259 }
00260 }
00261 }
00262
00263 # report to caller whether we are a temp item
00264 return ($this->Id() < 0) ? TRUE : FALSE;
00265 }
00266
00267 # get field attributes
00268 function Id() { return $this->DBFields["FieldId"]; }
00269 function DBFieldName() { return $this->DBFields["DBFieldName"]; }
00270
00271 # get/set field attributes
00272 function Description($NewValue = DB_NOVALUE)
00273 { return $this->UpdateValue("Description", $NewValue); }
00274 function Instructions($NewValue = DB_NOVALUE)
00275 { return $this->UpdateValue("Instructions", $NewValue); }
00276 function Owner($NewValue = DB_NOVALUE)
00277 { return $this->UpdateValue("Owner", $NewValue); }
00278 function RequiredBySPT($NewValue = DB_NOVALUE)
00279 { return $this->UpdateBoolValue("RequiredBySPT", $NewValue); }
00280 function Enabled($NewValue = DB_NOVALUE)
00281 { return $this->UpdateBoolValue("Enabled", $NewValue); }
00282 function Optional($NewValue = DB_NOVALUE)
00283 { return $this->UpdateBoolValue("Optional", $NewValue); }
00284 function Editable($NewValue = DB_NOVALUE)
00285 { return $this->UpdateBoolValue("Editable", $NewValue); }
00286 function Viewable($NewValue = DB_NOVALUE)
00287 { return $this->UpdateBoolValue("Viewable", $NewValue); }
00288 function AllowMultiple($NewValue = DB_NOVALUE)
00289 { return $this->UpdateBoolValue("AllowMultiple", $NewValue); }
00290 function IncludeInKeywordSearch($NewValue = DB_NOVALUE)
00291 { return $this->UpdateBoolValue("IncludeInKeywordSearch", $NewValue); }
00292 function IncludeInAdvancedSearch($NewValue = DB_NOVALUE)
00293 { return $this->UpdateBoolValue("IncludeInAdvancedSearch", $NewValue); }
00294 function IncludeInSortOptions($NewValue = DB_NOVALUE)
00295 { return $this->UpdateBoolValue("IncludeInSortOptions", $NewValue); }
00296 function IncludeInRecommenderSystem($NewValue = DB_NOVALUE)
00297 { return $this->UpdateBoolValue("IncludeInRecommenderSystem", $NewValue); }
00298 function TextFieldSize($NewValue = DB_NOVALUE)
00299 { return $this->UpdateIntValue("TextFieldSize", $NewValue); }
00300 function MaxLength($NewValue = DB_NOVALUE)
00301 { return $this->UpdateIntValue("MaxLength", $NewValue); }
00302 function ParagraphRows($NewValue = DB_NOVALUE)
00303 { return $this->UpdateIntValue("ParagraphRows", $NewValue); }
00304 function ParagraphCols($NewValue = DB_NOVALUE)
00305 { return $this->UpdateIntValue("ParagraphCols", $NewValue); }
00306 function MinValue($NewValue = DB_NOVALUE)
00307 { return $this->UpdateFloatValue("MinValue", $NewValue); }
00308 function MaxValue($NewValue = DB_NOVALUE)
00309 { return $this->UpdateFloatValue("MaxValue", $NewValue); }
00310 function FlagOnLabel($NewValue = DB_NOVALUE)
00311 { return $this->UpdateValue("FlagOnLabel", $NewValue); }
00312 function FlagOffLabel($NewValue = DB_NOVALUE)
00313 { return $this->UpdateValue("FlagOffLabel", $NewValue); }
00314 function DateFormat($NewValue = DB_NOVALUE)
00315 { return $this->UpdateValue("DateFormat", $NewValue); }
00316 function SearchWeight($NewValue = DB_NOVALUE)
00317 { return $this->UpdateIntValue("SearchWeight", $NewValue); }
00318 function RecommenderWeight($NewValue = DB_NOVALUE)
00319 { return $this->UpdateIntValue("RecommenderWeight", $NewValue); }
00320 function MaxHeight($NewValue = DB_NOVALUE)
00321 { return $this->UpdateIntValue("MaxHeight", $NewValue); }
00322 function MaxWidth($NewValue = DB_NOVALUE)
00323 { return $this->UpdateIntValue("MaxWidth", $NewValue); }
00324 function MaxPreviewHeight($NewValue = DB_NOVALUE)
00325 { return $this->UpdateIntValue("MaxPreviewHeight", $NewValue); }
00326 function MaxPreviewWidth($NewValue = DB_NOVALUE)
00327 { return $this->UpdateIntValue("MaxPreviewWidth", $NewValue); }
00328 function MaxThumbnailHeight($NewValue = DB_NOVALUE)
00329 { return $this->UpdateIntValue("MaxThumbnailHeight", $NewValue); }
00330 function MaxThumbnailWidth($NewValue = DB_NOVALUE)
00331 { return $this->UpdateIntValue("MaxThumbnailWidth", $NewValue); }
00332 function DefaultAltText($NewValue = DB_NOVALUE)
00333 { return $this->UpdateValue("DefaultAltText", $NewValue); }
00334 function UsesQualifiers($NewValue = DB_NOVALUE)
00335 { return $this->UpdateBoolValue("UsesQualifiers", $NewValue); }
00336 function ShowQualifiers($NewValue = DB_NOVALUE)
00337 { return $this->UpdateBoolValue("ShowQualifiers", $NewValue); }
00338 function DefaultQualifier($NewValue = DB_NOVALUE)
00339 { return $this->UpdateValue("DefaultQualifier", $NewValue); }
00340 function AllowHTML($NewValue = DB_NOVALUE)
00341 { return $this->UpdateBoolValue("AllowHTML", $NewValue); }
00342 function UseWysiwygEditor($NewValue = DB_NOVALUE)
00343 { return $this->UpdateBoolValue("UseWysiwygEditor", $NewValue); }
00344 function UseForOaiSets($NewValue = DB_NOVALUE)
00345 { return $this->UpdateBoolValue("UseForOaiSets", $NewValue); }
00346 function NumAjaxResults($NewValue = DB_NOVALUE)
00347 { return $this->UpdateIntValue("NumAjaxResults", $NewValue); }
00348 function ViewingPrivilege($NewValue = DB_NOVALUE)
00349 { return $this->UpdateConstValue("ViewingPrivilege", $NewValue); }
00350 function AuthoringPrivilege($NewValue = DB_NOVALUE)
00351 { return $this->UpdateConstValue("AuthoringPrivilege", $NewValue); }
00352 function EditingPrivilege($NewValue = DB_NOVALUE)
00353 { return $this->UpdateConstValue("EditingPrivilege", $NewValue); }
00354 function ImagePreviewPrivilege($NewValue = DB_NOVALUE)
00355 { return $this->UpdateConstValue("ImagePreviewPrivilege", $NewValue); }
00356 function TreeBrowsingPrivilege($NewValue = DB_NOVALUE)
00357 { return $this->UpdateConstValue("TreeBrowsingPrivilege", $NewValue); }
00358 function EnableOnOwnerReturn($NewValue = DB_NOVALUE)
00359 { return $this->UpdateBoolValue("EnableOnOwnerReturn", $NewValue); }
00360 function ViewingUserIsValue($NewValue = DB_NOVALUE)
00361 { return $this->UpdateConstValue("ViewingUserIsValue", $NewValue, "MetadataField"); }
00362 function AuthoringUserIsValue($NewValue = DB_NOVALUE)
00363 { return $this->UpdateConstValue("AuthoringUserIsValue", $NewValue, "MetadataField"); }
00364 function EditingUserIsValue($NewValue = DB_NOVALUE)
00365 { return $this->UpdateConstValue("EditingUserIsValue", $NewValue, "MetadataField"); }
00366 function ViewingUserValue($NewValue = DB_NOVALUE)
00367 { return $this->UpdateIntValue("ViewingUserValue", $NewValue, "MetadataField"); }
00368 function AuthoringUserValue($NewValue = DB_NOVALUE)
00369 { return $this->UpdateIntValue("AuthoringUserValue", $NewValue, "MetadataField"); }
00370 function EditingUserValue($NewValue = DB_NOVALUE)
00371 { return $this->UpdateIntValue("EditingUserValue", $NewValue, "MetadataField"); }
00372
00373 function UserPrivilegeRestrictions($NewValue = DB_NOVALUE)
00374 {
00375 # new value
00376 if ($NewValue != DB_NOVALUE)
00377 {
00378 $NewValue = serialize((array) $NewValue);
00379 }
00380
00381 $Value = $this->UpdateValue("UserPrivilegeRestrictions", $NewValue);
00382
00383 # value set
00384 if (strlen($Value))
00385 {
00386 $Value = (array) unserialize($Value);
00387 }
00388
00389 # no value set, set it to an empty array
00390 else
00391 {
00392 $Value = $this->UserPrivilegeRestrictions(array());
00393 }
00394
00395 return $Value;
00396 }
00397
00398 function PointPrecision($NewValue = DB_NOVALUE)
00399 {
00400 if ($NewValue !== DB_NOVALUE && $this->Id() >= 0)
00401 {
00402 $OldValue = $this->UpdateValue("PointPrecision", DB_NOVALUE);
00403
00404 if ($NewValue != $OldValue)
00405 {
00406 $Decimals = $this->UpdateValue("PointDecimalDigits", DB_NOVALUE);
00407
00408 $TotalDigits = $NewValue + $Decimals;
00409
00410
00411 $this->DB->Query("ALTER TABLE Resources MODIFY COLUMN "
00412 ."`".$this->DBFields["DBFieldName"]."X` "
00413 ."DECIMAL(".$TotalDigits.",".$Decimals.")");
00414 $this->DB->Query("ALTER TABLE Resources MODIFY COLUMN "
00415 ."`".$this->DBFields["DBFieldName"]."Y` "
00416 ."DECIMAL(".$TotalDigits.",".$Decimals.")");
00417 }
00418 }
00419
00420 return $this->UpdateValue("PointPrecision", $NewValue);
00421 }
00422
00423 function PointDecimalDigits($NewValue = DB_NOVALUE)
00424 {
00425 if ($NewValue !== DB_NOVALUE && $this->Id() >= 0)
00426 {
00427 $OldValue = $this->UpdateValue("PointDecimalDigits", DB_NOVALUE);
00428
00429 if ($NewValue != $OldValue)
00430 {
00431 $Precision = $this->UpdateValue("PointPrecision", DB_NOVALUE);
00432
00433 $TotalDigits = $NewValue + $Precision;
00434
00435 $this->DB->Query("ALTER TABLE Resources MODIFY COLUMN "
00436 ."`".$this->DBFields["DBFieldName"]."X` "
00437 ."DECIMAL(".$TotalDigits.",".$NewValue.")");
00438 $this->DB->Query("ALTER TABLE Resources MODIFY COLUMN "
00439 ."`".$this->DBFields["DBFieldName"]."Y` "
00440 ."DECIMAL(".$TotalDigits.",".$NewValue.")");
00441 }
00442 }
00443
00444 return $this->UpdateValue("PointDecimalDigits", $NewValue);
00445 }
00446
00447 function DefaultValue($NewValue = DB_NOVALUE)
00448 {
00449 if ($this->Type() == MetadataSchema::MDFTYPE_POINT)
00450 {
00451 if ($NewValue !== DB_NOVALUE &&
00452 isset($NewValue["X"]) && isset($NewValue["Y"]))
00453 {
00454 $NewValue = $NewValue["X"].",".$NewValue["Y"];
00455 }
00456
00457 $tmp = explode(",", $this->UpdateValue("DefaultValue", $NewValue));
00458
00459 if (count($tmp)==2)
00460 {
00461 return array("X" => $tmp[0], "Y" => $tmp[1]);
00462 }
00463
00464 return array("X" => NULL, "Y" => NULL);
00465 }
00466
00467 else if ($this->Type() == MetadataSchema::MDFTYPE_OPTION)
00468 {
00469 # multiple default values to set
00470 if (is_array($NewValue))
00471 {
00472 # empty array
00473 if (count($NewValue) == 0)
00474 {
00475 $NewValue = NULL;
00476 }
00477
00478 # multiple defaults are allowed
00479 else if ($this->AllowMultiple())
00480 {
00481 $NewValue = serialize($NewValue);
00482 }
00483
00484 # only one default is allowed so get the first one
00485 else
00486 {
00487 $NewValue = array_shift($NewValue);
00488 }
00489 }
00490
00491 $Result = $this->UpdateValue("DefaultValue", $NewValue);
00492
00493 return empty($Result) || is_numeric($Result) ?
00494 $Result : unserialize($Result);
00495 }
00496
00497 return $this->UpdateValue("DefaultValue", $NewValue);
00498 }
00499
00505 function UpdateMethod($NewValue = DB_NOVALUE)
00506 {
00507 return $this->UpdateValue("UpdateMethod", $NewValue);
00508 }
00509
00510 # get possible values (only meaningful for Trees, Controlled Names, Options,
00511 # Flags, and Users)
00512 # (index for returned array is IDs for values)
00513 function GetPossibleValues($MaxNumberOfValues = NULL, $Offset=0)
00514 {
00515 # retrieve values based on field type
00516 switch ($this->Type())
00517 {
00518 case MetadataSchema::MDFTYPE_TREE:
00519 $QueryString = "SELECT ClassificationId, ClassificationName"
00520 ." FROM Classifications WHERE FieldId = ".$this->Id()
00521 ." ORDER BY ClassificationName";
00522 if ($MaxNumberOfValues)
00523 {
00524 $QueryString .= " LIMIT ".intval($MaxNumberOfValues)." OFFSET "
00525 .intval($Offset);
00526 }
00527 $this->DB->Query($QueryString);
00528 $PossibleValues = $this->DB->FetchColumn(
00529 "ClassificationName", "ClassificationId");
00530 break;
00531
00532 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
00533 case MetadataSchema::MDFTYPE_OPTION:
00534 $QueryString = "SELECT ControlledNameId, ControlledName"
00535 ." FROM ControlledNames WHERE FieldId = ".$this->Id()
00536 ." ORDER BY ControlledName";
00537 if ($MaxNumberOfValues)
00538 {
00539 $QueryString .= " LIMIT ".intval($MaxNumberOfValues)." OFFSET "
00540 .intval($Offset);
00541 }
00542 $this->DB->Query($QueryString);
00543 $PossibleValues = $this->DB->FetchColumn(
00544 "ControlledName", "ControlledNameId");
00545 break;
00546
00547 case MetadataSchema::MDFTYPE_FLAG:
00548 $PossibleValues[0] = $this->FlagOffLabel();
00549 $PossibleValues[1] = $this->FlagOnLabel();
00550 break;
00551
00552 case MetadataSchema::MDFTYPE_USER:
00553 $UserFactory = new UserFactory($this->DB);
00554 $Restrictions = $this->UserPrivilegeRestrictions();
00555 $PossibleValues = array();
00556
00557 if (count($Restrictions))
00558 {
00559 $PossibleValues = call_user_func_array(
00560 array($UserFactory, "GetUsersWithPrivileges"),
00561 $Restrictions);
00562 }
00563
00564 else
00565 {
00566 $Users = $UserFactory->GetMatchingUsers(".*.");
00567
00568 foreach ($Users as $Id => $Data)
00569 {
00570 $PossibleValues[$Id] = $Data["UserName"];
00571 }
00572 }
00573
00574 break;
00575
00576 default:
00577 # for everything else return an empty array
00578 $PossibleValues = array();
00579 break;
00580 }
00581
00582 # return array of possible values to caller
00583 return $PossibleValues;
00584 }
00585
00586 # get count of possible values (only meaningful for Trees, Controlled Names,
00587 # Options, and Users)
00588 function GetCountOfPossibleValues()
00589 {
00590 # retrieve values based on field type
00591 switch ($this->Type())
00592 {
00593 case MetadataSchema::MDFTYPE_TREE:
00594 $Count = $this->DB->Query("SELECT count(*) AS ValueCount"
00595 ." FROM Classifications WHERE FieldId = ".$this->Id(),
00596 "ValueCount");
00597 break;
00598
00599 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
00600 case MetadataSchema::MDFTYPE_OPTION:
00601 $Count = $this->DB->Query("SELECT count(*) AS ValueCount"
00602 ." FROM ControlledNames WHERE FieldId = ".$this->Id(),
00603 "ValueCount");
00604 break;
00605
00606 case MetadataSchema::MDFTYPE_FLAG:
00607 $Count = 2;
00608 break;
00609
00610 case MetadataSchema::MDFTYPE_USER:
00611 $Count = count($this->GetPossibleValues());
00612 break;
00613
00614 default:
00615 # for everything else return an empty array
00616 $Count = 0;
00617 break;
00618 }
00619
00620 # return count of possible values to caller
00621 return $Count;
00622 }
00623
00624 # get ID for specified value (only meaningful for Trees / Controlled Names / Options)
00625 # (returns NULL if value not found)
00626 function GetIdForValue($Value)
00627 {
00628 # retrieve ID based on field type
00629 switch ($this->Type())
00630 {
00631 case MetadataSchema::MDFTYPE_TREE:
00632 $Id = $this->DB->Query("SELECT ClassificationId FROM Classifications"
00633 ." WHERE ClassificationName = '".addslashes($Value)."'"
00634 ." AND FieldId = ".$this->Id(),
00635 "ClassificationId");
00636 break;
00637
00638 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
00639 case MetadataSchema::MDFTYPE_OPTION:
00640 $Id = $this->DB->Query("SELECT ControlledNameId FROM ControlledNames"
00641 ." WHERE ControlledName = '".addslashes($Value)."'"
00642 ." AND FieldId = ".$this->Id(),
00643 "ControlledNameId");
00644 break;
00645
00646 default:
00647 # for everything else return NULL
00648 $Id = NULL;
00649 break;
00650 }
00651
00652 # return ID for value to caller
00653 return $Id;
00654 }
00655
00656 # get value for specified ID (only meaningful for Trees / Controlled Names / Options)
00657 # (returns NULL if ID not found)
00658 function GetValueForId($Id)
00659 {
00660 # retrieve ID based on field type
00661 switch ($this->Type())
00662 {
00663 case MetadataSchema::MDFTYPE_TREE:
00664 $Value = $this->DB->Query("SELECT ClassificationName FROM Classifications"
00665 ." WHERE ClassificationId = '".intval($Id)."'"
00666 ." AND FieldId = ".$this->Id(),
00667 "ClassificationName");
00668 break;
00669
00670 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
00671 case MetadataSchema::MDFTYPE_OPTION:
00672 $Value = $this->DB->Query("SELECT ControlledName FROM ControlledNames"
00673 ." WHERE ControlledNameId = '".intval($Id)."'"
00674 ." AND FieldId = ".$this->Id(),
00675 "ControlledName");
00676 break;
00677
00678 default:
00679 # for everything else return NULL
00680 $Value = NULL;
00681 break;
00682 }
00683
00684 # return ID for value to caller
00685 return $Value;
00686 }
00687
00688
00689
00690 # get/set whether field uses item-level qualifiers
00691 function HasItemLevelQualifiers($NewValue = DB_NOVALUE)
00692 {
00693 # if value provided different from present value
00694 if (($NewValue != DB_NOVALUE)
00695 && ($NewValue != $this->DBFields["HasItemLevelQualifiers"]))
00696 {
00697 # check if qualifier column currently exists
00698 $QualColName = $this->DBFieldName()."Qualifier";
00699 $QualColExists = $this->DB->FieldExists("Resources", $QualColName);
00700
00701 # if new value indicates qualifiers should now be used
00702 if ($NewValue == TRUE)
00703 {
00704 # if qualifier column does not exist in DB for this field
00705 if ($QualColExists == FALSE)
00706 {
00707 # add qualifier column in DB for this field
00708 $this->DB->Query("ALTER TABLE Resources ADD COLUMN `"
00709 .$QualColName."` INT");
00710 }
00711 }
00712 else
00713 {
00714 # if qualifier column exists in DB for this field
00715 if ($QualColExists == TRUE)
00716 {
00717 # remove qualifier column from DB for this field
00718 $this->DB->Query("ALTER TABLE Resources DROP COLUMN `"
00719 .$QualColName."`");
00720 }
00721 }
00722 }
00723
00724 return $this->UpdateValue("HasItemLevelQualifiers", $NewValue);
00725 }
00726
00727 # get list of qualifiers associated with field
00728 function AssociatedQualifierList()
00729 {
00730 # start with empty list
00731 $List = array();
00732
00733 # for each associated qualifier
00734 $this->DB->Query("SELECT QualifierId FROM FieldQualifierInts"
00735 ." WHERE MetadataFieldId = ".$this->DBFields["FieldId"]);
00736 while ($Record = $this->DB->FetchRow())
00737 {
00738 # load qualifier object
00739 $Qual = new Qualifier($Record["QualifierId"]);
00740
00741 # add qualifier ID and name to list
00742 $List[$Qual->Id()] = $Qual->Name();
00743 }
00744
00745 # return list to caller
00746 return $List;
00747 }
00748
00749 # get list of qualifiers not associated with field
00750 function UnassociatedQualifierList()
00751 {
00752 # grab list of associated qualifiers
00753 $AssociatedQualifiers = $this->AssociatedQualifierList();
00754
00755 # get list of all qualifiers
00756 $QFactory = new QualifierFactory();
00757 $AllQualifiers = $QFactory->QualifierList();
00758
00759 # return list of unassociated qualifiers
00760 return array_diff($AllQualifiers, $AssociatedQualifiers);
00761 }
00762
00763 # add qualifier association
00764 function AssociateWithQualifier($QualifierIdOrObject)
00765 {
00766 # if qualifier object passed in
00767 if (is_object($QualifierIdOrObject))
00768 {
00769 # grab qualifier ID from object
00770 $QualifierIdOrObject = $QualifierIdOrObject->Id();
00771 }
00772
00773 # if not already associated
00774 $RecordCount = $this->DB->Query(
00775 "SELECT COUNT(*) AS RecordCount FROM FieldQualifierInts"
00776 ." WHERE QualifierId = ".$QualifierIdOrObject
00777 ." AND MetadataFieldId = ".$this->Id(), "RecordCount");
00778 if ($RecordCount < 1)
00779 {
00780 # associate field with qualifier
00781 $this->DB->Query("INSERT INTO FieldQualifierInts SET"
00782 ." QualifierId = ".$QualifierIdOrObject.","
00783 ." MetadataFieldId = ".$this->Id());
00784 }
00785 }
00786
00787 # delete qualifier association
00788 function UnassociateWithQualifier($QualifierIdOrObject)
00789 {
00790 # if qualifier object passed in
00791 if (is_object($QualifierIdOrObject))
00792 {
00793 # grab qualifier ID from object
00794 $QualifierIdOrObject = $QualifierIdOrObject->Id();
00795 }
00796
00797 # delete intersection record from database
00798 $this->DB->Query("DELETE FROM FieldQualifierInts WHERE QualifierId = "
00799 .$QualifierIdOrObject." AND MetadataFieldId = ".
00800 $this->Id());
00801 }
00802
00803 # retrieve item factory object for this field
00804 function GetFactory()
00805 {
00806 switch ($this->Type())
00807 {
00808 case MetadataSchema::MDFTYPE_TREE:
00809 $Factory = new ClassificationFactory($this->Id());
00810 break;
00811
00812 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
00813 case MetadataSchema::MDFTYPE_OPTION:
00814 $Factory = new ControlledNameFactory($this->Id());
00815 break;
00816
00817 default:
00818 $Factory = NULL;
00819 break;
00820 }
00821
00822 return $Factory;
00823 }
00824
00825
00826 # ---- PRIVATE INTERFACE -------------------------------------------------
00827
00828 private $DB;
00829 private $DBFields;
00830 private $ErrorStatus;
00831
00832 # field type DB/PHP enum translations
00833 public static $FieldTypeDBEnums = array(
00834 MetadataSchema::MDFTYPE_TEXT => "Text",
00835 MetadataSchema::MDFTYPE_PARAGRAPH => "Paragraph",
00836 MetadataSchema::MDFTYPE_NUMBER => "Number",
00837 MetadataSchema::MDFTYPE_DATE => "Date",
00838 MetadataSchema::MDFTYPE_TIMESTAMP => "TimeStamp",
00839 MetadataSchema::MDFTYPE_FLAG => "Flag",
00840 MetadataSchema::MDFTYPE_TREE => "Tree",
00841 MetadataSchema::MDFTYPE_CONTROLLEDNAME => "ControlledName",
00842 MetadataSchema::MDFTYPE_OPTION => "Option",
00843 MetadataSchema::MDFTYPE_USER => "User",
00844 MetadataSchema::MDFTYPE_IMAGE => "Still Image",
00845 MetadataSchema::MDFTYPE_FILE => "File",
00846 MetadataSchema::MDFTYPE_URL => "Url",
00847 MetadataSchema::MDFTYPE_POINT => "Point"
00848 );
00849 public static $FieldTypeDBAllowedEnums = array(
00850 MetadataSchema::MDFTYPE_TEXT => "Text",
00851 MetadataSchema::MDFTYPE_PARAGRAPH => "Paragraph",
00852 MetadataSchema::MDFTYPE_NUMBER => "Number",
00853 MetadataSchema::MDFTYPE_DATE => "Date",
00854 MetadataSchema::MDFTYPE_TIMESTAMP => "TimeStamp",
00855 MetadataSchema::MDFTYPE_FLAG => "Flag",
00856 MetadataSchema::MDFTYPE_TREE => "Tree",
00857 MetadataSchema::MDFTYPE_CONTROLLEDNAME => "ControlledName",
00858 MetadataSchema::MDFTYPE_OPTION => "Option",
00859 MetadataSchema::MDFTYPE_USER => "User",
00860 MetadataSchema::MDFTYPE_IMAGE => "Still Image",
00861 MetadataSchema::MDFTYPE_FILE => "File",
00862 MetadataSchema::MDFTYPE_URL => "Url",
00863 MetadataSchema::MDFTYPE_POINT => "Point"
00864 );
00865 public static $FieldTypePHPEnums = array(
00866 "Text" => MetadataSchema::MDFTYPE_TEXT,
00867 "Paragraph" => MetadataSchema::MDFTYPE_PARAGRAPH,
00868 "Number" => MetadataSchema::MDFTYPE_NUMBER,
00869 "Date" => MetadataSchema::MDFTYPE_DATE,
00870 "TimeStamp" => MetadataSchema::MDFTYPE_TIMESTAMP,
00871 "Flag" => MetadataSchema::MDFTYPE_FLAG,
00872 "Tree" => MetadataSchema::MDFTYPE_TREE,
00873 "ControlledName" => MetadataSchema::MDFTYPE_CONTROLLEDNAME,
00874 "Option" => MetadataSchema::MDFTYPE_OPTION,
00875 "User" => MetadataSchema::MDFTYPE_USER,
00876 "Still Image" => MetadataSchema::MDFTYPE_IMAGE,
00877 "File" => MetadataSchema::MDFTYPE_FILE,
00878 "Url" => MetadataSchema::MDFTYPE_URL,
00879 "Point" => MetadataSchema::MDFTYPE_POINT
00880 );
00881
00882 public static $UpdateTypes = array(
00883 MetadataField::UPDATEMETHOD_NOAUTOUPDATE => "Do not update automatically",
00884 MetadataField::UPDATEMETHOD_ONRECORDCREATE => "Update on record creation",
00885 MetadataField::UPDATEMETHOD_BUTTON => "Provide an update button",
00886 MetadataField::UPDATEMETHOD_ONRECORDEDIT => "Update when record is edited",
00887 MetadataField::UPDATEMETHOD_ONRECORDCHANGE => "Update when record is changed"
00888 );
00889
00890
00891 # object constructor (only for use by MetadataSchema object)
00892 function MetadataField($FieldId, $FieldName = NULL, $FieldType = NULL,
00893 $Optional = TRUE, $DefaultValue = NULL)
00894 {
00895 # assume everything will be okay
00896 $this->ErrorStatus = MetadataSchema::MDFSTAT_OK;
00897
00898 # grab our own database handle
00899 $this->DB = new Database();
00900 $DB = $this->DB;
00901
00902 # if field ID supplied
00903 if ($FieldId != NULL)
00904 {
00905 # look up field in database
00906 $DB->Query("SELECT * FROM MetadataFields WHERE FieldId = ".intval($FieldId));
00907 $Record = $DB->FetchRow();
00908 }
00909
00910 # if no field ID supplied or if record not found in database
00911 if (($FieldId == NULL) || ($Record == NULL))
00912 {
00913 # error out if valid field type not supplied
00914 if (empty(MetadataField::$FieldTypeDBEnums[$FieldType]))
00915 {
00916 $this->ErrorStatus = MetadataSchema::MDFSTAT_FIELDDOESNOTEXIST;
00917 return;
00918 }
00919
00920 # if field name supplied
00921 $FieldName = trim($FieldName);
00922 if (strlen($FieldName) > 0)
00923 {
00924 # error out if field name is duplicate
00925 $DuplicateCount = $DB->Query("
00926 SELECT COUNT(*) AS RecordCount FROM MetadataFields
00927 WHERE FieldName = '".addslashes($FieldName)."'
00928 OR Label = '".addslashes($FieldName)."'",
00929 "RecordCount");
00930
00931 if ($DuplicateCount > 0)
00932 {
00933 $this->ErrorStatus = MetadataSchema::MDFSTAT_DUPLICATENAME;
00934 return;
00935 }
00936 }
00937
00938 # grab current user ID
00939 global $G_User;
00940 $UserId = $G_User->Get("UserId");
00941
00942 # lock DB tables and get next temporary field ID
00943 $Schema = new MetadataSchema();
00944 $DB->Query("LOCK TABLES MetadataFields WRITE");
00945 $FieldId = $Schema->GetNextTempItemId();
00946
00947 # add field to MDF table in database
00948 $DB->Query("INSERT INTO MetadataFields "
00949 ."(FieldId, FieldName, FieldType, Optional,"
00950 ." DefaultValue, LastModifiedById) VALUES "
00951 ."(".intval($FieldId).", "
00952 ."'".addslashes($FieldName)."', "
00953 ."'".MetadataField::$FieldTypeDBEnums[$FieldType]."', "
00954 .($Optional ? 1 : 0).", "
00955 ."'".addslashes($DefaultValue)."',"
00956 ."'".$UserId."')");
00957
00958 # release DB tables
00959 $DB->Query("UNLOCK TABLES");
00960
00961 # re-read record from database
00962 $DB->Query("SELECT * FROM MetadataFields WHERE FieldId = "
00963 .intval($FieldId));
00964 $this->DBFields = $DB->FetchRow();
00965 $this->DBFields["DBFieldName"] =
00966 $this->NormalizeFieldNameForDB($this->DBFields["FieldName"]);
00967
00968 # set field order values for new field
00969 $FieldCount = $DB->Query("SELECT COUNT(*) AS FieldCount"
00970 ." FROM MetadataFields", "FieldCount");
00971 $this->OrderPosition(MetadataSchema::MDFORDER_DISPLAY, ($FieldCount + 1));
00972 $this->OrderPosition(MetadataSchema::MDFORDER_EDITING, ($FieldCount + 1));
00973
00974 # set other field defaults
00975 $this->SearchWeight(($FieldType & (MetadataSchema::MDFTYPE_OPTION
00976 |MetadataSchema::MDFTYPE_CONTROLLEDNAME)) ? 3 : 1);
00977 }
00978 else
00979 {
00980 # save values locally
00981 $this->DBFields = $Record;
00982 $this->DBFields["DBFieldName"] =
00983 $this->NormalizeFieldNameForDB($Record["FieldName"]);
00984 }
00985 }
00986
00987 # remove field from database (only for use by MetadataSchema object)
00988 function Drop()
00989 {
00990 # clear other database entries as appropriate for field type
00991 $DB = $this->DB;
00992 $DBFieldName = $this->DBFields["DBFieldName"];
00993 switch (MetadataField::$FieldTypePHPEnums[$this->DBFields["FieldType"]])
00994 {
00995 case MetadataSchema::MDFTYPE_TEXT:
00996 case MetadataSchema::MDFTYPE_PARAGRAPH:
00997 case MetadataSchema::MDFTYPE_NUMBER:
00998 case MetadataSchema::MDFTYPE_USER:
00999 case MetadataSchema::MDFTYPE_IMAGE:
01000 case MetadataSchema::MDFTYPE_TIMESTAMP:
01001 case MetadataSchema::MDFTYPE_URL:
01002 # remove field from resources table
01003 if ($DB->FieldExists("Resources", $DBFieldName))
01004 {
01005 $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."`");
01006 }
01007 break;
01008
01009 case MetadataSchema::MDFTYPE_POINT:
01010 if ($DB->FieldExists("Resources", $DBFieldName."X"))
01011 {
01012 $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."X`");
01013 $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."Y`");
01014 }
01015 break;
01016
01017 case MetadataSchema::MDFTYPE_FLAG:
01018 # remove field from resources table
01019 if ($DB->FieldExists("Resources", $DBFieldName))
01020 {
01021 $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."`");
01022 }
01023 break;
01024
01025 case MetadataSchema::MDFTYPE_DATE:
01026 # remove fields from resources table
01027 if ($DB->FieldExists("Resources", $DBFieldName."Begin"))
01028 {
01029 $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."Begin`");
01030 $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."End`");
01031 $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."Precision`");
01032 }
01033 break;
01034
01035 case MetadataSchema::MDFTYPE_TREE:
01036 $DB->Query("SELECT ClassificationId FROM Classifications "
01037 ."WHERE FieldId = ".$this->Id());
01038 $TempDB = new SPTDatabase();
01039 while ($ClassificationId = $DB->FetchField("ClassificationId"))
01040 {
01041 # remove any resource / name intersections
01042 $TempDB->Query("DELETE FROM ResourceClassInts WHERE "
01043 ."ClassificationId = ".$ClassificationId);
01044
01045 # remove controlled name
01046 $TempDB->Query("DELETE FROM Classifications WHERE "
01047 ."ClassificationId = ".$ClassificationId);
01048 }
01049 break;
01050
01051 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
01052 case MetadataSchema::MDFTYPE_OPTION:
01053 $DB->Query("SELECT ControlledNameId FROM ControlledNames "
01054 ."WHERE FieldId = ".$this->Id());
01055 $TempDB = new SPTDatabase();
01056 while ($ControlledNameId = $DB->FetchField("ControlledNameId"))
01057 {
01058 # remove any resource / name intersections
01059 $TempDB->Query("DELETE FROM ResourceNameInts WHERE "
01060 ."ControlledNameId = ".$ControlledNameId);
01061
01062 # remove any variant names
01063 $TempDB->Query("DELETE FROM VariantNames WHERE "
01064 ."ControlledNameId = ".$ControlledNameId);
01065
01066 # remove controlled name
01067 $TempDB->Query("DELETE FROM ControlledNames WHERE "
01068 ."ControlledNameId = ".$ControlledNameId);
01069 }
01070 break;
01071
01072 case MetadataSchema::MDFTYPE_FILE:
01073 # for each file associated with this field
01074 $DB->Query("SELECT FileId FROM Files WHERE FieldId = '".$this->Id()."'");
01075 while ($FileId = $DB->FetchRow())
01076 {
01077 # delete file
01078 $File = new File(intval($FileId));
01079 $File->Delete();
01080 }
01081 break;
01082 }
01083
01084 # remove field from database
01085 $DB->Query("DELETE FROM MetadataFields "
01086 ."WHERE FieldId = '".$this->DBFields["FieldId"]."'");
01087
01088 # remove any qualifier associations
01089 $DB->Query("DELETE FROM FieldQualifierInts WHERE MetadataFieldId = '"
01090 .$this->DBFields["FieldId"]."'");
01091 }
01092
01093 # get/set field order positions (intended only for use by MetadataSchema object)
01094 function OrderPosition($OrderType, $NewValue = DB_NOVALUE)
01095 {
01096 switch ($OrderType)
01097 {
01098 case MetadataSchema::MDFORDER_DISPLAY:
01099 return $this->UpdateValue("DisplayOrderPosition", $NewValue);
01100 break;
01101
01102 case MetadataSchema::MDFORDER_EDITING:
01103 return $this->UpdateValue("EditingOrderPosition", $NewValue);
01104 break;
01105
01106 default:
01107 exit("invalid order type passed to MetadataField::OrderPosition");
01108 break;
01109 }
01110 }
01111
01112 # modify any database fields
01113 private function ModifyField($NewName = NULL, $NewType = NULL)
01114 {
01115 # grab old DB field name
01116 $OldDBFieldName = $this->DBFields["DBFieldName"];
01117 $OldFieldType = NULL;
01118
01119 # if new field name supplied
01120 if ($NewName != NULL)
01121 {
01122 # cache the old name for options and controllednames below
01123 $OldName = $this->DBFields["FieldName"];
01124
01125 # store new name
01126 $this->UpdateValue("FieldName", $NewName);
01127
01128 # determine new DB field name
01129 $NewDBFieldName = $this->NormalizeFieldNameForDB($NewName);
01130
01131 # store new database field name
01132 $this->DBFields["DBFieldName"] = $NewDBFieldName;
01133 }
01134 else
01135 {
01136 # set new field name equal to old field name
01137 $NewDBFieldName = $OldDBFieldName;
01138 }
01139
01140 # if new type supplied
01141 if ($NewType != NULL)
01142 {
01143 # grab old field type
01144 $OldFieldType = MetadataField::$FieldTypePHPEnums[$this->DBFields["FieldType"]];
01145
01146 # store new field type
01147 $this->UpdateValue("FieldType", MetadataField::$FieldTypeDBEnums[$NewType]);
01148 }
01149
01150 # if this is not a temporary field
01151 if ($this->Id() >= 0)
01152 {
01153 # modify field in DB as appropriate for field type
01154 $DB = $this->DB;
01155 $FieldType = MetadataField::$FieldTypePHPEnums[$this->DBFields["FieldType"]];
01156 switch ($FieldType)
01157 {
01158 case MetadataSchema::MDFTYPE_TEXT:
01159 case MetadataSchema::MDFTYPE_PARAGRAPH:
01160 case MetadataSchema::MDFTYPE_URL:
01161 # alter field declaration in Resources table
01162 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
01163 .$OldDBFieldName."` `"
01164 .$NewDBFieldName."` TEXT "
01165 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
01166 break;
01167
01168 case MetadataSchema::MDFTYPE_NUMBER:
01169 case MetadataSchema::MDFTYPE_USER:
01170 # alter field declaration in Resources table
01171 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
01172 .$OldDBFieldName."` `"
01173 .$NewDBFieldName."` INT "
01174 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
01175 break;
01176
01177 case MetadataSchema::MDFTYPE_POINT:
01178 $Precision = $this->UpdateValue("PointPrecision",
01179 DB_NOVALUE);
01180 $Digits = $this->UpdateValue("PointDecimalDigits",
01181 DB_NOVALUE);
01182 $DB->Query("ALTER TABLE Resources CHANGE COLUMN "
01183 ."`".$OldDBFieldName."X` "
01184 ."`".$NewDBFieldName."X`".
01185 " DECIMAL(".$Precision.",".$Digits.")");
01186 $DB->Query("ALTER TABLE Resources CHANGE COLUMN "
01187 ."`".$OldDBFieldName."Y` "
01188 ."`".$NewDBFieldName."Y`".
01189 " DECIMAL(".$Precision.",".$Digits.")");
01190 break;
01191
01192 case MetadataSchema::MDFTYPE_FILE:
01193 # if DB field name has changed
01194 if ($NewDBFieldName != $OldDBFieldName)
01195 {
01196 # alter field declaration in Resources table
01197 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
01198 .$OldDBFieldName."` `"
01199 .$NewDBFieldName."` TEXT");
01200 }
01201 break;
01202
01203 case MetadataSchema::MDFTYPE_IMAGE:
01204 # if DB field name has changed
01205 if ($NewDBFieldName != $OldDBFieldName)
01206 {
01207 # alter field declaration in Resources table
01208 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
01209 .$OldDBFieldName."` `"
01210 .$NewDBFieldName."` INT");
01211 }
01212 break;
01213
01214 case MetadataSchema::MDFTYPE_FLAG:
01215 # alter field declaration in Resources table
01216 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
01217 .$OldDBFieldName."` `"
01218 .$NewDBFieldName."` INT"
01219 ." DEFAULT ".intval($this->DefaultValue()));
01220
01221 # set any unset values to default
01222 $DB->Query("UPDATE Resources SET `".$NewDBFieldName
01223 ."` = ".intval($this->DefaultValue())
01224 ." WHERE `".$NewDBFieldName."` IS NULL");
01225 break;
01226
01227 case MetadataSchema::MDFTYPE_DATE:
01228 # if new type supplied and new type is different from old
01229 if (($NewType != NULL) && ($NewType != $OldFieldType))
01230 {
01231 # if old type was time stamp
01232 if ($OldFieldType == MetadataSchema::MDFTYPE_TIMESTAMP)
01233 {
01234 # change time stamp field in resources table to begin date
01235 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
01236 .$OldDBFieldName."` `"
01237 .$NewDBFieldName."Begin` DATE "
01238 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
01239
01240 # add end date and precision fields
01241 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$NewDBFieldName."End"
01242 ."` DATE");
01243 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$NewDBFieldName."Precision`"
01244 ." INT ".($Optional ? "" : "NOT NULL"));
01245
01246 # set precision to reflect time stamp content
01247 $DB->Query("UPDATE Resources SET `".$NewDBFieldName."Precision` = "
01248 .(DATEPRE_BEGINYEAR|DATEPRE_BEGINMONTH|DATEPRE_BEGINDAY));
01249 }
01250 else
01251 {
01252 exit("<br>ERROR: Attempt to convert metadata field to date from type other than timestamp<br>\n");
01253 }
01254 }
01255 else
01256 {
01257 # change name of fields
01258 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
01259 .$OldDBFieldName."Begin` `"
01260 .$NewDBFieldName."Begin` DATE "
01261 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
01262 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
01263 .$OldDBFieldName."End` `"
01264 .$NewDBFieldName."End` DATE "
01265 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
01266 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
01267 .$OldDBFieldName."Precision` `"
01268 .$NewDBFieldName."Precision` INT "
01269 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
01270 }
01271 break;
01272
01273 case MetadataSchema::MDFTYPE_TIMESTAMP:
01274 # if new type supplied and new type is different from old
01275 if (($NewType != NULL) && ($NewType != $OldFieldType))
01276 {
01277 # if old type was date
01278 if ($OldFieldType == MetadataSchema::MDFTYPE_DATE)
01279 {
01280 # change begin date field in resource table to time stamp
01281 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
01282 .$OldDBFieldName."Begin` `"
01283 .$NewDBFieldName."` DATETIME "
01284 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
01285
01286 # drop end date and precision fields
01287 $DB->Query("ALTER TABLE Resources DROP COLUMN `"
01288 .$OldDBFieldName."End`");
01289 $DB->Query("ALTER TABLE Resources DROP COLUMN `"
01290 .$OldDBFieldName."Precision`");
01291 }
01292 else
01293 {
01294 exit("<br>ERROR: Attempt to convert metadata field to time stamp from type other than date<br>\n");
01295 }
01296 }
01297 else
01298 {
01299 # change name of field
01300 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
01301 .$OldDBFieldName."` `"
01302 .$NewDBFieldName."` DATETIME "
01303 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
01304 }
01305 break;
01306
01307 case MetadataSchema::MDFTYPE_TREE:
01308 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
01309 case MetadataSchema::MDFTYPE_OPTION:
01310 break;
01311 }
01312
01313 # if qualifier DB field exists
01314 if ($DB->FieldExists("Resources", $OldDBFieldName."Qualifier"))
01315 {
01316 # rename qualifier DB field
01317 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
01318 .$OldDBFieldName."Qualifier` `"
01319 .$NewDBFieldName."Qualifier` INT ");
01320 }
01321 }
01322 }
01323
01324 # convenience functions to supply parameters to Database->UpdateValue()
01325 private function UpdateValue($FieldName, $NewValue)
01326 {
01327 return $this->DB->UpdateValue("MetadataFields", $FieldName, $NewValue,
01328 "FieldId = ".intval($this->DBFields["FieldId"]),
01329 $this->DBFields);
01330 }
01331 private function UpdateIntValue($FieldName, $NewValue)
01332 {
01333 return $this->DB->UpdateIntValue("MetadataFields", $FieldName, $NewValue,
01334 "FieldId = ".intval($this->DBFields["FieldId"]),
01335 $this->DBFields);
01336 }
01337 private function UpdateFloatValue($FieldName, $NewValue)
01338 {
01339 return $this->DB->UpdateFloatValue("MetadataFields", $FieldName, $NewValue,
01340 "FieldId = ".intval($this->DBFields["FieldId"]),
01341 $this->DBFields);
01342 }
01343 private function UpdateBoolValue($FieldName, $NewValue)
01344 {
01345 $NewValue = $this->TranslateStringToConstants($NewValue);
01346 return $this->DB->UpdateIntValue("MetadataFields", $FieldName, $NewValue,
01347 "FieldId = ".intval($this->DBFields["FieldId"]),
01348 $this->DBFields);
01349 }
01350 private function UpdateConstValue($FieldName, $NewValue, $ClassName=NULL)
01351 {
01352 $NewValue = $this->TranslateStringToConstants($NewValue, $ClassName);
01353 return $this->DB->UpdateIntValue("MetadataFields", $FieldName, $NewValue,
01354 "FieldId = ".intval($this->DBFields["FieldId"]),
01355 $this->DBFields);
01356 }
01357
01358 # normalize field name for use as database field name
01359 private function NormalizeFieldNameForDB($Name)
01360 {
01361 return preg_replace("/[^a-z0-9]/i", "", $Name);
01362 }
01363
01364 # add any needed database fields and/or entries
01365 private function AddDatabaseFields()
01366 {
01367 # grab values for common use
01368 $DB = $this->DB;
01369 $FieldName = $this->Name();
01370 $DBFieldName = $this->DBFieldName();
01371 $Optional = $this->Optional();
01372 $DefaultValue = $this->DefaultValue();
01373
01374 # set up field(s) based on field type
01375 switch ($this->Type())
01376 {
01377 case MetadataSchema::MDFTYPE_TEXT:
01378 case MetadataSchema::MDFTYPE_PARAGRAPH:
01379 case MetadataSchema::MDFTYPE_URL:
01380 # add field to resources table (if not already present)
01381 if (!$DB->FieldExists("Resources", $DBFieldName))
01382 {
01383 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
01384 ."` TEXT ".($Optional ? "" : "NOT NULL"));
01385 }
01386
01387 # if default value supplied
01388 if ($DefaultValue != NULL)
01389 {
01390 # set all existing records to default value
01391 $DB->Query("UPDATE Resources SET `"
01392 .$DBFieldName."` = '".addslashes($DefaultValue)."'");
01393 }
01394 break;
01395
01396 case MetadataSchema::MDFTYPE_NUMBER:
01397 # add field to resources table (if not already present)
01398 if (!$DB->FieldExists("Resources", $DBFieldName))
01399 {
01400 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
01401 ."` INT ".($Optional ? "" : "NOT NULL"));
01402 }
01403
01404 # if default value supplied
01405 if ($DefaultValue != NULL)
01406 {
01407 # set all existing records to default value
01408 $DB->Query("UPDATE Resources SET `"
01409 .$DBFieldName."` = '".addslashes($DefaultValue)."'");
01410 }
01411 break;
01412
01413 case MetadataSchema::MDFTYPE_POINT:
01414 if (!$DB->FieldExists("Resources", $DBFieldName."X"))
01415 {
01416 $Precision = $this->UpdateValue("PointPrecision",
01417 DB_NOVALUE);
01418 $Digits = $this->UpdateValue("PointDecimalDigits",
01419 DB_NOVALUE);
01420
01421 $DB->Query("ALTER TABLE Resources ADD COLUMN `"
01422 .$DBFieldName."X`".
01423 " DECIMAL(".$Precision.",".$Digits.")");
01424 $DB->Query("ALTER TABLE Resources ADD COLUMN `"
01425 .$DBFieldName."Y`".
01426 " DECIMAL(".$Precision.",".$Digits.")");
01427 }
01428
01429 break;
01430 case MetadataSchema::MDFTYPE_FLAG:
01431 # if field is not already present in database
01432 if (!$DB->FieldExists("Resources", $DBFieldName))
01433 {
01434 # add field to resources table
01435 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
01436 ."` INT DEFAULT ".intval($DefaultValue));
01437
01438 # set all existing records to default value
01439 $DB->Query("UPDATE Resources SET `"
01440 .$DBFieldName."` = ".intval($DefaultValue));
01441 }
01442 break;
01443
01444 case MetadataSchema::MDFTYPE_USER:
01445 # add field to resources table (if not already present)
01446 if (!$DB->FieldExists("Resources", $DBFieldName))
01447 {
01448 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
01449 ."` INT ".($Optional ? "" : "NOT NULL"));
01450 }
01451 break;
01452
01453 case MetadataSchema::MDFTYPE_FILE:
01454 # add fields to resources table (if not already present)
01455 if (!$DB->FieldExists("Resources", $DBFieldName))
01456 {
01457 $DB->Query("ALTER TABLE Resources ADD COLUMN `"
01458 .$DBFieldName."` TEXT");
01459 }
01460 break;
01461
01462 case MetadataSchema::MDFTYPE_IMAGE:
01463 # add fields to resources table (if not already present)
01464 if (!$DB->FieldExists("Resources", $DBFieldName))
01465 {
01466 $DB->Query("ALTER TABLE Resources ADD COLUMN `"
01467 .$DBFieldName."` INT");
01468 }
01469 break;
01470
01471 case MetadataSchema::MDFTYPE_DATE:
01472 # add fields to resources table (if not already present)
01473 if (!$DB->FieldExists("Resources", $DBFieldName."Begin"))
01474 {
01475 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName."Begin`"
01476 ." DATE ".($Optional ? "" : "NOT NULL"));
01477 }
01478 if (!$DB->FieldExists("Resources", $DBFieldName."End"))
01479 {
01480 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName."End`"
01481 ." DATE");
01482 }
01483 if (!$DB->FieldExists("Resources", $DBFieldName."Precision"))
01484 {
01485 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName."Precision`"
01486 ." INT ".($Optional ? "" : "NOT NULL"));
01487 }
01488 break;
01489
01490 case MetadataSchema::MDFTYPE_TIMESTAMP:
01491 # add fields to resources table (if not already present)
01492 if (!$DB->FieldExists("Resources", $DBFieldName))
01493 {
01494 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
01495 ."` DATETIME ".($Optional ? "" : "NOT NULL"));
01496 }
01497 break;
01498
01499 case MetadataSchema::MDFTYPE_TREE:
01500 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
01501 case MetadataSchema::MDFTYPE_OPTION:
01502 break;
01503
01504 default:
01505 exit("<br>ERROR: Attempt to add database fields for illegal metadata field type<br>\n");
01506 break;
01507 }
01508 }
01509
01517 private function TranslateStringToConstants($CString, $ClassName = NULL)
01518 {
01519 # if not a string return value unchanged to caller
01520 if (!is_string($CString) || ($CString === DB_NOVALUE))
01521 {
01522 $ReturnValue = $CString;
01523 }
01524 # handle booleans as a special case
01525 elseif (strtoupper(trim($CString)) == "TRUE")
01526 {
01527 $ReturnValue = TRUE;
01528 }
01529 elseif (strtoupper(trim($CString)) == "FALSE")
01530 {
01531 $ReturnValue = FALSE;
01532 }
01533 else
01534 {
01535 # assume no values will be found
01536 $ReturnValue = NULL;
01537
01538 # split apart any ORed-together values
01539 $Values = explode("|", $CString);
01540
01541 # for each value found
01542 foreach ($Values as $Value)
01543 {
01544 # trim off any extraneous whitespace
01545 $Value = trim($Value);
01546
01547 # add class name prefix to constant name if requested
01548 if ($ClassName) { $Value = $ClassName."::".$Value; }
01549
01550 # if value corresponds to a constant
01551 if (defined($Value))
01552 {
01553 # add constant to return value
01554 $ReturnValue = ($ReturnValue === NULL)
01555 ? constant($Value)
01556 : ($ReturnValue | constant($Value));
01557 }
01558 }
01559
01560 # if no corresponding constants were found
01561 if ($ReturnValue === NULL)
01562 {
01563 # return original value to caller
01564 $ReturnValue = $CString;
01565 }
01566 }
01567
01568 # return result to caller
01569 return $ReturnValue;
01570 }
01571 }