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 ?>

Copyright 2010 Internet Scout