Search:

CWIS Developers Documentation

  • Main Page
  • Classes
  • Files
  • File List
  • File Members

MetadataSchema.php

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

CWIS logo doxygen
Copyright 2010 Internet Scout