00001 <?PHP 00002 00003 # 00004 # FILE: SPT--MetadataSchema.php 00005 # 00006 # METHODS PROVIDED: 00007 # MetadataSchema() 00008 # - constructor 00009 # AddField($FieldName, $FieldType, $Optional = FALSE, $DefaultValue = NULL) 00010 # - add new metadata field 00011 # DropField($FieldId) 00012 # - delete metadata field 00013 # GetField($FieldId) 00014 # - retrieve field by ID 00015 # GetFieldByName($FieldName) 00016 # - retrieve field by name 00017 # GetFields($FieldTypes = NULL) 00018 # - retrieve array of fields 00019 # GetFieldTypes() 00020 # - retrieve array of field types (enumerated type => field name) 00021 # GetAllowedFieldTypes() 00022 # - retrieve array of field types that user can create (enumerated type => field name) 00023 # Status() { return $this->ErrorStatus; } 00024 # - return current error status of schema object 00025 # RemoveQualifierAssociations($QualifierIdOrObject) 00026 # - remove all metadata field associations for a given qualifier 00027 # QualifierIsInUse($QualifierIdOrObject) 00028 # - return whether qualifier is in use by metadata field 00029 # (SEE ALSO: SPT--ItemFactory.php) 00030 # 00031 # AUTHOR: Edward Almasy 00032 # 00033 # Part of the Scout Portal Toolkit 00034 # Copyright 2002-2003 Internet Scout Project 00035 # http://scout.wisc.edu 00036 # 00037 00038 class MetadataSchema extends ItemFactory { 00039 00040 # ---- PUBLIC INTERFACE -------------------------------------------------- 00041 00042 # types of field ordering 00043 const MDFORDER_DISPLAY = 1; 00044 const MDFORDER_EDITING = 2; 00045 00046 # metadata field types 00047 # (must parallel MetadataFields.FieldType declaration in SPT--CreateTables.sql 00048 # and MetadataField::$FieldTypeDBEnums declaration below) 00049 const MDFTYPE_TEXT = 1; 00050 const MDFTYPE_PARAGRAPH = 2; 00051 const MDFTYPE_NUMBER = 4; 00052 const MDFTYPE_DATE = 8; 00053 const MDFTYPE_TIMESTAMP = 16; 00054 const MDFTYPE_FLAG = 32; 00055 const MDFTYPE_TREE = 64; 00056 const MDFTYPE_CONTROLLEDNAME = 128; 00057 const MDFTYPE_OPTION = 256; 00058 const MDFTYPE_USER = 512; 00059 const MDFTYPE_IMAGE = 1024; 00060 const MDFTYPE_FILE = 2048; 00061 const MDFTYPE_URL = 4096; 00062 const MDFTYPE_POINT = 8192; 00063 00064 # error status codes 00065 const MDFSTAT_OK = 1; 00066 const MDFSTAT_DUPLICATENAME = 2; 00067 const MDFSTAT_DUPLICATEDBCOLUMN = 4; 00068 const MDFSTAT_ILLEGALNAME = 8; 00069 const MDFSTAT_FIELDDOESNOTEXIST = 16; 00070 00071 # object constructor 00072 function MetadataSchema() 00073 { 00074 # set up item factory base class 00075 $this->ItemFactory("MetadataField", "MetadataFields", "FieldId"); 00076 00077 # start with field info caching enabled 00078 $this->CachingOn = TRUE; 00079 } 00080 00081 # turn internal caching of field info on or off 00082 function CacheData($NewValue) 00083 { 00084 $this->CachingOn = $NewValue; 00085 } 00086 00087 # add new metadata field 00088 function AddField($FieldName, $FieldType, $Optional = TRUE, $DefaultValue = NULL) 00089 { 00090 # create new field 00091 $Field = new MetadataField(NULL, $FieldName, $FieldType, $Optional, $DefaultValue); 00092 00093 # save error code if create failed and return NULL 00094 if ($Field->Status() != MetadataSchema::MDFSTAT_OK) 00095 { 00096 $this->ErrorStatus = $Field->Status(); 00097 $Field = NULL; 00098 } 00099 00100 # return new field to caller 00101 return $Field; 00102 } 00103 00104 # delete metadata field 00105 function DropField($FieldId) 00106 { 00107 $Field = new MetadataField($FieldId); 00108 $Field->Drop(); 00109 } 00110 00111 # retrieve field by ID 00112 function GetField($FieldId) 00113 { 00114 static $Fields; 00115 00116 # if caching is off or field is already loaded 00117 if (($this->CachingOn != TRUE) || !isset($Fields[$FieldId])) 00118 { 00119 # retrieve field 00120 $Fields[$FieldId] = new MetadataField($FieldId); 00121 } 00122 00123 # return field to caller 00124 return $Fields[$FieldId]; 00125 } 00126 00127 # retrieve field by name 00128 function GetFieldByName($FieldName, $IgnoreCase = FALSE) 00129 { 00130 $FieldId = $this->GetFieldIdByName($FieldName, $IgnoreCase); 00131 return ($FieldId === NULL) ? NULL : $this->GetField($FieldId); 00132 } 00133 00134 # retrieve field ID by name 00135 function GetFieldIdByName($FieldName, $IgnoreCase = FALSE) 00136 { 00137 static $FieldIdsByName; 00138 00139 # if caching is off or field ID is already loaded 00140 if (($this->CachingOn != TRUE) || !isset($FieldIdsByName[$FieldName])) 00141 { 00142 # retrieve field ID from DB 00143 $Condition = $IgnoreCase 00144 ? "WHERE LOWER(FieldName) = '".addslashes(strtolower($FieldName))."'" 00145 : "WHERE FieldName = '".addslashes($FieldName)."'"; 00146 $FieldIdsByName[$FieldName] = $this->DB->Query( 00147 "SELECT FieldId FROM MetadataFields ".$Condition, "FieldId"); 00148 } 00149 00150 return $FieldIdsByName[$FieldName]; 00151 } 00152 00153 # check whether field with specified name exists 00154 function FieldExists($FieldName) 00155 { 00156 return $this->GetFieldByName($FieldName) ? TRUE : FALSE; 00157 } 00158 00159 # retrieve array of fields 00160 function GetFields($FieldTypes = NULL, $OrderType = NULL, $IncludeDisabledFields = FALSE, $IncludeTempFields = FALSE) 00161 { 00162 # create empty array to pass back 00163 $Fields = array(); 00164 00165 # for each field type in database 00166 if ($IncludeTempFields && $IncludeDisabledFields) 00167 { 00168 $this->DB->Query("SELECT FieldId, FieldType FROM MetadataFields"); 00169 } 00170 else 00171 { 00172 if ($IncludeTempFields) 00173 { 00174 $this->DB->Query("SELECT FieldId, FieldType FROM MetadataFields WHERE Enabled != 0"); 00175 } 00176 elseif ($IncludeDisabledFields) 00177 { 00178 $this->DB->Query("SELECT FieldId, FieldType FROM MetadataFields WHERE FieldId >= 0"); 00179 } 00180 else 00181 { 00182 $this->DB->Query("SELECT FieldId, FieldType FROM MetadataFields WHERE FieldId >= 0 AND Enabled != 0"); 00183 } 00184 } 00185 while ($Record = $this->DB->FetchRow()) 00186 { 00187 # if no specific type requested or if field is of requested type 00188 if (($FieldTypes == NULL) 00189 || (MetadataField::$FieldTypePHPEnums[$Record["FieldType"]] & $FieldTypes)) 00190 { 00191 # create field object and add to array to be passed back 00192 $Fields[$Record["FieldId"]] = new MetadataField($Record["FieldId"]); 00193 } 00194 } 00195 00196 # if field sorting requested 00197 if ($OrderType !== NULL) 00198 { 00199 # sort field array by requested order type 00200 $this->FieldCompareType = $OrderType; 00201 $MSFieldOrderError = FALSE; 00202 uasort($Fields, array($this, "CompareFieldOrder")); 00203 00204 # if field order error detected 00205 global $MSFieldOrderError; 00206 if ($MSFieldOrderError) 00207 { 00208 # repair (reset) field order 00209 $OrderIndex = 1; 00210 foreach ($Fields as $Field) 00211 { 00212 $Field->OrderPosition($OrderType, $OrderIndex); 00213 $OrderIndex++; 00214 } 00215 } 00216 } 00217 00218 # return array of field objects to caller 00219 return $Fields; 00220 } 00221 00222 function GetFieldNames($FieldTypes = NULL, $OrderType = NULL, 00223 $IncludeDisabledFields = FALSE, $IncludeTempFields = FALSE) 00224 { 00225 global $DB; 00226 00227 $FieldNames=array(); 00228 $Fields = $this->GetFields($FieldTypes, $OrderType, $IncludeDisabledFields, $IncludeTempFields); 00229 00230 foreach($Fields as $Field) 00231 { 00232 $DB->Query("SELECT FieldName FROM MetadataFields WHERE FieldId=".$Field->Id()); 00233 $FieldNames[ $Field->Id() ] = $DB->FetchField("FieldName"); 00234 } 00235 00236 return $FieldNames; 00237 } 00238 00239 00240 # retrieve array of field types (enumerated type => field name) 00241 function GetFieldTypes() 00242 { 00243 return MetadataField::$FieldTypeDBEnums; 00244 } 00245 00246 # retrieve array of field types that user can create (enumerated type => field name) 00247 function GetAllowedFieldTypes() 00248 { 00249 return MetadataField::$FieldTypeDBAllowedEnums; 00250 } 00251 00252 # remove all metadata field associations for a given qualifier 00253 function RemoveQualifierAssociations($QualifierIdOrObject) 00254 { 00255 # sanitize qualifier ID or grab it from object 00256 $QualifierIdOrObject = is_object($QualifierIdOrObject) 00257 ? $QualifierIdOrObject->Id() : intval($QualifierIdOrObject); 00258 00259 # delete intersection records from database 00260 $this->DB->Query("DELETE FROM FieldQualifierInts WHERE QualifierId = " 00261 .$QualifierIdOrObject); 00262 } 00263 00264 # return whether qualifier is in use by metadata field 00265 function QualifierIsInUse($QualifierIdOrObject) 00266 { 00267 # sanitize qualifier ID or grab it from object 00268 $QualifierIdOrObject = is_object($QualifierIdOrObject) 00269 ? $QualifierIdOrObject->Id() : intval($QualifierIdOrObject); 00270 00271 # determine whether any fields use qualifier as default 00272 $DefaultCount = $this->DB->Query("SELECT COUNT(*) AS RecordCount FROM MetadataFields" 00273 ." WHERE DefaultQualifier = ".$QualifierIdOrObject, 00274 "RecordCount"); 00275 00276 # determine whether any fields are associated with qualifier 00277 $AssociationCount = $this->DB->Query("SELECT COUNT(*) AS RecordCount FROM FieldQualifierInts" 00278 ." WHERE QualifierId = ".$QualifierIdOrObject, 00279 "RecordCount"); 00280 00281 # report whether qualifier is in use based on defaults and associations 00282 return (($DefaultCount + $AssociationCount) > 0) ? TRUE : FALSE; 00283 } 00284 00285 # move fields up or down in field order 00286 function MoveUpInOrder($FieldIdOrObj, $OrderType) 00287 { 00288 $this->MoveFieldInOrder($FieldIdOrObj, $OrderType, FALSE); 00289 } 00290 function MoveDownInOrder($FieldIdOrObj, $OrderType) 00291 { 00292 $this->MoveFieldInOrder($FieldIdOrObj, $OrderType, TRUE); 00293 } 00294 00295 # return highest field ID currently in use 00296 function GetHighestFieldId() 00297 { 00298 return $this->GetHighestItemId(); 00299 } 00300 00301 00302 # ---- PRIVATE INTERFACE ------------------------------------------------- 00303 00304 var $FieldCompareType; 00305 var $CachingOn; 00306 00307 function MoveFieldInOrder($FieldIdOrObj, $OrderType, $MoveFieldDown) 00308 { 00309 # grab field ID 00310 $FieldId = is_object($FieldIdOrObj) ? $Field->Id() : $FieldIdOrObj; 00311 00312 # retrieve array of fields 00313 $Fields = $this->GetFields(NULL, $OrderType); 00314 00315 # reverse array of fields if we are moving field down 00316 if ($MoveFieldDown) 00317 { 00318 $Fields = array_reverse($Fields); 00319 } 00320 00321 # for each field in order 00322 $PreviousField = NULL; 00323 foreach ($Fields as $Field) 00324 { 00325 # if field is the field to be moved 00326 if ($Field->Id() == $FieldId) 00327 { 00328 # if we have a previous field 00329 if ($PreviousField !== NULL) 00330 { 00331 # swap field with previous field according to order type 00332 $TempVal = $Field->OrderPosition($OrderType); 00333 $Field->OrderPosition($OrderType, $PreviousField->OrderPosition($OrderType)); 00334 $PreviousField->OrderPosition($OrderType, $TempVal); 00335 } 00336 } 00337 00338 # save field for next iteration 00339 $PreviousField = $Field; 00340 } 00341 } 00342 00343 # callback function for sorting fields 00344 function CompareFieldOrder($FieldA, $FieldB) 00345 { 00346 if ($FieldA->OrderPosition($this->FieldCompareType) == $FieldB->OrderPosition($this->FieldCompareType)) 00347 { 00348 global $MSFieldOrderError; 00349 $MSFieldOrderError = TRUE; 00350 return 0; 00351 } 00352 else 00353 { 00354 return ($FieldA->OrderPosition($this->FieldCompareType) < $FieldB->OrderPosition($this->FieldCompareType)) ? -1 : 1; 00355 } 00356 } 00357 } 00358 00359 ?>