MetadataField.php

Go to the documentation of this file.
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 }